lambda expressions (the java™ tutorials _ learning the java language _ classes and objects)

Upload: deepanshujain

Post on 06-Mar-2016

19 views

Category:

Documents


0 download

DESCRIPTION

Lamda Has been introduced to Java 8 Version. Here is an overview

TRANSCRIPT

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 1/10

    Trail:LearningtheJavaLanguageLesson:ClassesandObjectsSection:NestedClasses

    LambdaExpressions

    Oneissuewithanonymousclassesisthatiftheimplementationofyouranonymousclassisverysimple,suchasaninterfacethatcontainsonlyonemethod,thenthesyntaxofanonymousclassesmayseemunwieldyandunclear.Inthesecases,you'reusuallytryingtopassfunctionalityasanargumenttoanothermethod,suchaswhatactionshouldbetakenwhensomeoneclicksabutton.Lambdaexpressionsenableyoutodothis,totreatfunctionalityasmethodargument,orcodeasdata.

    Theprevioussection,AnonymousClasses,showsyouhowtoimplementabaseclasswithoutgivingitaname.Althoughthisisoftenmoreconcisethananamedclass,forclasseswithonlyonemethod,evenananonymousclassseemsabitexcessiveandcumbersome.Lambdaexpressionsletyouexpressinstancesofsinglemethodclassesmorecompactly.

    Thissectioncoversthefollowingtopics:

    IdealUseCaseforLambdaExpressionsApproach1:CreateMethodsThatSearchforMembersThatMatchOneCharacteristicApproach2:CreateMoreGeneralizedSearchMethodsApproach3:SpecifySearchCriteriaCodeinaLocalClassApproach4:SpecifySearchCriteriaCodeinanAnonymousClassApproach5:SpecifySearchCriteriaCodewithaLambdaExpressionApproach6:UseStandardFunctionalInterfaceswithLambdaExpressionsApproach7:UseLambdaExpressionsThroughoutYourApplicationApproach8:UseGenericsMoreExtensivelyApproach9:UseAggregateOperationsThatAcceptLambdaExpressionsasParameters

    LambdaExpressionsinGUIApplicationsSyntaxofLambdaExpressionsAccessingLocalVariablesoftheEnclosingScopeTargetTyping

    TargetTypesandMethodArgumentsSerialization

    IdealUseCaseforLambdaExpressions

    Supposethatyouarecreatingasocialnetworkingapplication.Youwanttocreateafeaturethatenablesanadministratortoperformanykindofaction,suchassendingamessage,onmembersofthesocialnetworkingapplicationthatsatisfycertaincriteria.Thefollowingtabledescribesthisusecaseindetail:

    Field Description

    Name Performactiononselectedmembers

    PrimaryActor Administrator

    Preconditions Administratorisloggedintothesystem.

    Postconditions Actionisperformedonlyonmembersthatfitthespecifiedcriteria.

    MainSuccessScenario

    1. Administratorspecifiescriteriaofmembersonwhichtoperformacertainaction.2. Administratorspecifiesanactiontoperformonthoseselectedmembers.3. AdministratorselectstheSubmitbutton.4. Thesystemfindsallmembersthatmatchthespecifiedcriteria.5. Thesystemperformsthespecifiedactiononallmatchingmembers.

    Extensions 1a.AdministratorhasanoptiontopreviewthosememberswhomatchthespecifiedcriteriabeforeheorshespecifiestheactiontobeperformedorbeforeselectingtheSubmitbutton.

    FrequencyofOccurrence

    Manytimesduringtheday.

    SupposethatmembersofthissocialnetworkingapplicationarerepresentedbythefollowingPersonclass:

    Documentation

    TheJavaTutorials

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 2/10

    publicclassPerson{

    publicenumSex{

    MALE,FEMALE

    }

    Stringname

    LocalDatebirthday

    Sexgender

    StringemailAddress

    publicintgetAge(){

    //...

    }

    publicvoidprintPerson(){

    //...

    }

    }

    SupposethatthemembersofyoursocialnetworkingapplicationarestoredinaListinstance.

    Thissectionbeginswithanaiveapproachtothisusecase.Itimprovesuponthisapproachwithlocalandanonymousclasses,andthenfinisheswithanefficientandconciseapproachusinglambdaexpressions.FindthecodeexcerptsdescribedinthissectionintheexampleRosterTest.

    Approach1:CreateMethodsThatSearchforMembersThatMatchOneCharacteristic

    Onesimplisticapproachistocreateseveralmethodseachmethodsearchesformembersthatmatchonecharacteristic,suchasgenderorage.Thefollowingmethodprintsmembersthatareolderthanaspecifiedage:

    publicstaticvoidprintPersonsOlderThan(Listroster,intage){

    for(Personp:roster){

    if(p.getAge()>=age){

    p.printPerson()

    }

    }

    }

    Note:AListisanorderedCollection.Acollectionisanobjectthatgroupsmultipleelementsintoasingleunit.Collectionsareusedtostore,retrieve,manipulate,andcommunicateaggregatedata.Formoreinformationaboutcollections,seetheCollectionstrail.

    Thisapproachcanpotentiallymakeyourapplicationbrittle,whichisthelikelihoodofanapplicationnotworkingbecauseoftheintroductionofupdates(suchasnewerdatatypes).SupposethatyouupgradeyourapplicationandchangethestructureofthePersonclasssuchthatitcontainsdifferentmembervariablesperhapstheclassrecordsandmeasuresageswithadifferentdatatypeoralgorithm.YouwouldhavetorewritealotofyourAPItoaccommodatethischange.Inaddition,thisapproachisunnecessarilyrestrictivewhatifyouwantedtoprintmembersyoungerthanacertainage,forexample?

    Approach2:CreateMoreGeneralizedSearchMethods

    ThefollowingmethodismoregenericthanprintPersonsOlderThanitprintsmemberswithinaspecifiedrangeofages:

    publicstaticvoidprintPersonsWithinAgeRange(

    Listroster,intlow,inthigh){

    for(Personp:roster){

    if(low

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 3/10

    }

    }

    ThismethodcheckseachPersoninstancecontainedintheListparameterrosterwhetheritsatisfiesthesearchcriteriaspecifiedintheCheckPersonparametertesterbyinvokingthemethodtester.test.Ifthemethodtester.testreturnsatruevalue,thenthemethodprintPersonsisinvokedonthePersoninstance.

    Tospecifythesearchcriteria,youimplementtheCheckPersoninterface:

    interfaceCheckPerson{

    booleantest(Personp)

    }

    ThefollowingclassimplementstheCheckPersoninterfacebyspecifyinganimplementationforthemethodtest.ThismethodfiltersmembersthatareeligibleforSelectiveServiceintheUnitedStates:itreturnsatruevalueifitsPersonparameterismaleandbetweentheagesof18and25:

    classCheckPersonEligibleForSelectiveServiceimplementsCheckPerson{

    publicbooleantest(Personp){

    returnp.gender==Person.Sex.MALE&&

    p.getAge()>=18&&

    p.getAge()p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 4/10

    booleantest(Personp)

    }

    Thisisaverysimpleinterface.It'safunctionalinterfacebecauseitcontainsonlyoneabstractmethod.Thismethodtakesoneparameterandreturnsabooleanvalue.Themethodissosimplethatitmightnotbeworthittodefineoneinyourapplication.Consequently,theJDKdefinesseveralstandardfunctionalinterfaces,whichyoucanfindinthepackagejava.util.function.

    Forexample,youcanusethePredicateinterfaceinplaceofCheckPerson.Thisinterfacecontainsthemethodbooleantest(Tt):

    interfacePredicate{

    booleantest(Tt)

    }

    TheinterfacePredicateisanexampleofagenericinterface.(Formoreinformationaboutgenerics,seetheGenerics(Updated)lesson.)Generictypes(suchasgenericinterfaces)specifyoneormoretypeparameterswithinanglebrackets().Thisinterfacecontainsonlyonetypeparameter,T.Whenyoudeclareorinstantiateagenerictypewithactualtypearguments,youhaveaparameterizedtype.Forexample,theparameterizedtypePredicateisthefollowing:

    interfacePredicate{

    booleantest(Persont)

    }

    ThisparameterizedtypecontainsamethodthathasthesamereturntypeandparametersasCheckPerson.booleantest(Personp).Consequently,youcanusePredicateinplaceofCheckPersonasthefollowingmethoddemonstrates:

    publicstaticvoidprintPersonsWithPredicate(

    Listroster,Predicatetester){

    for(Personp:roster){

    if(tester.test(p)){

    p.printPerson()

    }

    }

    }

    Asaresult,thefollowingmethodinvocationisthesameaswhenyouinvokedprintPersonsinApproach3:SpecifySearchCriteriaCodeinaLocalClasstoobtainmemberswhoareeligibleforSelectiveService:

    printPersonsWithPredicate(

    roster,

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 5/10

    if(tester.test(p)){

    block.accept(p)

    }

    }

    }

    Asaresult,thefollowingmethodinvocationisthesameaswhenyouinvokedprintPersonsinApproach3:SpecifySearchCriteriaCodeinaLocalClasstoobtainmemberswhoareeligibleforSelectiveService.Thelambdaexpressionusedtoprintmembersishighlighted:

    processPersons(

    roster,

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()p.printPerson()

    )

    Whatifyouwanttodomorewithyourmembers'profilesthanprintingthemout.Supposethatyouwanttovalidatethemembers'profilesorretrievetheircontactinformation?Inthiscase,youneedafunctionalinterfacethatcontainsanabstractmethodthatreturnsavalue.TheFunctioninterfacecontainsthemethodRapply(Tt).Thefollowingmethodretrievesthedataspecifiedbytheparametermapper,andthenperformsanactiononitspecifiedbytheparameterblock:

    publicstaticvoidprocessPersonsWithFunction(

    Listroster,

    Predicatetester,

    Functionmapper,

    Consumerblock){

    for(Personp:roster){

    if(tester.test(p)){

    Stringdata=mapper.apply(p)

    block.accept(data)

    }

    }

    }

    ThefollowingmethodretrievestheemailaddressfromeachmembercontainedinrosterwhoiseligibleforSelectiveServiceandthenprintsit:

    processPersonsWithFunction(

    roster,

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()p.getEmailAddress(),

    email>System.out.println(email)

    )

    Approach8:UseGenericsMoreExtensively

    ReconsiderthemethodprocessPersonsWithFunction.Thefollowingisagenericversionofitthataccepts,asaparameter,acollectionthatcontainselementsofanydatatype:

    publicstaticvoidprocessElements(

    Iterablesource,

    Predicatetester,

    Functionmapper,

    Consumerblock){

    for(Xp:source){

    if(tester.test(p)){

    Ydata=mapper.apply(p)

    block.accept(data)

    }

    }

    }

    ToprinttheemailaddressofmemberswhoareeligibleforSelectiveService,invoketheprocessElementsmethodasfollows:

    processElements(

    roster,

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()p.getEmailAddress(),

    email>System.out.println(email)

    )

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 6/10

    Thismethodinvocationperformsthefollowingactions:

    1. Obtainsasourceofobjectsfromthecollectionsource.Inthisexample,itobtainsasourceofPersonobjectsfromthecollectionroster.Noticethatthecollectionroster,whichisacollectionoftypeList,isalsoanobjectoftypeIterable.

    2. FiltersobjectsthatmatchthePredicateobjecttester.Inthisexample,thePredicateobjectisalambdaexpressionthatspecifieswhichmemberswouldbeeligibleforSelectiveService.

    3. MapseachfilteredobjecttoavalueasspecifiedbytheFunctionobjectmapper.Inthisexample,theFunctionobjectisalambdaexpressionthatreturnstheemailaddressofamember.

    4. PerformsanactiononeachmappedobjectasspecifiedbytheConsumerobjectblock.Inthisexample,theConsumerobjectisalambdaexpressionthatprintsastring,whichistheemailaddressreturnedbytheFunctionobject.

    Youcanreplaceeachoftheseactionswithanaggregateoperation.

    Approach9:UseAggregateOperationsThatAcceptLambdaExpressionsasParameters

    ThefollowingexampleusesaggregateoperationstoprinttheemailaddressesofthosememberscontainedinthecollectionrosterwhoareeligibleforSelectiveService:

    roster

    .stream()

    .filter(

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()p.getEmailAddress())

    .forEach(email>System.out.println(email))

    ThefollowingtablemapseachoftheoperationsthemethodprocessElementsperformswiththecorrespondingaggregateoperation:

    processElementsAction AggregateOperation

    Obtainasourceofobjects Streamstream()

    FilterobjectsthatmatchaPredicateobject Streamfilter(Predicate

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 7/10

    Acommaseparatedlistofformalparametersenclosedinparentheses.TheCheckPerson.testmethodcontainsoneparameter,p,whichrepresentsaninstanceofthePersonclass.

    Note:Youcanomitthedatatypeoftheparametersinalambdaexpression.Inaddition,youcanomittheparenthesesifthereisonlyoneparameter.Forexample,thefollowinglambdaexpressionisalsovalid:

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()

    Abody,whichconsistsofasingleexpressionorastatementblock.Thisexampleusesthefollowingexpression:

    p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge(){

    returnp.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()System.out.println(email)

    Notethatalambdaexpressionlooksalotlikeamethoddeclarationyoucanconsiderlambdaexpressionsasanonymousmethodsmethodswithoutaname.

    Thefollowingexample,Calculator,isanexampleoflambdaexpressionsthattakemorethanoneformalparameter:

    publicclassCalculator{

    interfaceIntegerMath{

    intoperation(inta,intb)

    }

    publicintoperateBinary(inta,intb,IntegerMathop){

    returnop.operation(a,b)

    }

    publicstaticvoidmain(String...args){

    CalculatormyApp=newCalculator()

    IntegerMathaddition=(a,b)>a+b

    IntegerMathsubtraction=(a,b)>ab

    System.out.println("40+2="+

    myApp.operateBinary(40,2,addition))

    System.out.println("2010="+

    myApp.operateBinary(20,10,subtraction))

    }

    }

    ThemethodoperateBinaryperformsamathematicaloperationontwointegeroperands.TheoperationitselfisspecifiedbyaninstanceofIntegerMath.Theexampledefinestwooperationswithlambdaexpressions,additionandsubtraction.Theexampleprintsthefollowing:

    40+2=42

    2010=10

    AccessingLocalVariablesoftheEnclosingScope

    Likelocalandanonymousclasses,lambdaexpressionscancapturevariablestheyhavethesameaccesstolocalvariablesoftheenclosingscope.However,unlikelocalandanonymousclasses,lambdaexpressionsdonothaveanyshadowingissues(seeShadowingformoreinformation).Lambdaexpressionsarelexicallyscoped.Thismeansthattheydonotinheritanynamesfromasupertypeorintroduceanewlevelofscoping.Declarationsinalambdaexpressionareinterpretedjustastheyareintheenclosingenvironment.Thefollowingexample,LambdaScopeTest,demonstratesthis:

    importjava.util.function.Consumer

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 8/10

    publicclassLambdaScopeTest{

    publicintx=0

    classFirstLevel{

    publicintx=1

    voidmethodInFirstLevel(intx){

    //Thefollowingstatementcausesthecompilertogenerate

    //theerror"localvariablesreferencedfromalambdaexpression

    //mustbefinaloreffectivelyfinal"instatementA:

    //

    //x=99

    ConsumermyConsumer=(y)>

    {

    System.out.println("x="+x)//StatementA

    System.out.println("y="+y)

    System.out.println("this.x="+this.x)

    System.out.println("LambdaScopeTest.this.x="+

    LambdaScopeTest.this.x)

    }

    myConsumer.accept(x)

    }

    }

    publicstaticvoidmain(String...args){

    LambdaScopeTestst=newLambdaScopeTest()

    LambdaScopeTest.FirstLevelfl=st.newFirstLevel()

    fl.methodInFirstLevel(23)

    }

    }

    Thisexamplegeneratesthefollowingoutput:

    x=23

    y=23

    this.x=1

    LambdaScopeTest.this.x=0

    IfyousubstitutetheparameterxinplaceofyinthedeclarationofthelambdaexpressionmyConsumer,thenthecompilergeneratesanerror:

    ConsumermyConsumer=(x)>{

    //...

    }

    Thecompilergeneratestheerror"variablexisalreadydefinedinmethodmethodInFirstLevel(int)"becausethelambdaexpressiondoesnotintroduceanewlevelofscoping.Consequently,youcandirectlyaccessfields,methods,andlocalvariablesoftheenclosingscope.Forexample,thelambdaexpressiondirectlyaccessestheparameterxofthemethodmethodInFirstLevel.Toaccessvariablesintheenclosingclass,usethekeywordthis.Inthisexample,this.xreferstothemembervariableFirstLevel.x.

    However,likelocalandanonymousclasses,alambdaexpressioncanonlyaccesslocalvariablesandparametersoftheenclosingblockthatarefinaloreffectivelyfinal.Forexample,supposethatyouaddthefollowingassignmentstatementimmediatelyafterthemethodInFirstLeveldefinitionstatement:

    voidmethodInFirstLevel(intx){

    x=99

    //...

    }

    Becauseofthisassignmentstatement,thevariableFirstLevel.xisnoteffectivelyfinalanymore.Asaresult,theJavacompilergeneratesanerrormessagesimilarto"localvariablesreferencedfromalambdaexpressionmustbefinaloreffectivelyfinal"wherethelambdaexpressionmyConsumertriestoaccesstheFirstLevel.xvariable:

    System.out.println("x="+x)

    TargetTyping

    Howdoyoudeterminethetypeofalambdaexpression?Recallthelambdaexpressionthatselectedmemberswhoaremaleandbetweentheages18and25years:

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 9/10

    p>p.getGender()==Person.Sex.MALE

    &&p.getAge()>=18

    &&p.getAge()"done")

    Themethodinvoke(Callable)willbeinvokedbecausethatmethodreturnsavaluethemethodinvoke(Runnable)doesnot.Inthiscase,thetypeofthelambdaexpression()>"done"isCallable.

    Serialization

    Youcanserializealambdaexpressionifitstargettypeanditscapturedargumentsareserializable.However,likeinnerclasses,theserializationoflambdaexpressionsisstronglydiscouraged.

    Youruseofthispageandallthematerialonpagesunder"TheJavaTutorials"bannerissubjecttotheselegalnotices.

    Copyright1995,2015Oracleand/oritsaffiliates.Allrightsreserved.

    Problemswiththeexamples?TryCompilingandRunningtheExamples:FAQs.

  • 5/3/2015 LambdaExpressions(TheJavaTutorials>LearningtheJavaLanguage>ClassesandObjects)

    https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 10/10

    Complaints?Compliments?Suggestions?Giveusyourfeedback.

    Previouspage:AnonymousClassesNextpage:MethodReferences