Lambda Expressions (The Java™ Tutorials _ Learning the Java Language _ Classes and Objects)

Download Lambda Expressions (The Java™ Tutorials _ Learning the Java Language _ Classes and Objects)

Post on 06-Mar-2016

6 views

Category:

Documents

0 download

Embed Size (px)

DESCRIPTION

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

TRANSCRIPT

<ul><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 1/10</p><p>Trail:LearningtheJavaLanguageLesson:ClassesandObjectsSection:NestedClasses</p><p>LambdaExpressions</p><p>Oneissuewithanonymousclassesisthatiftheimplementationofyouranonymousclassisverysimple,suchasaninterfacethatcontainsonlyonemethod,thenthesyntaxofanonymousclassesmayseemunwieldyandunclear.Inthesecases,you'reusuallytryingtopassfunctionalityasanargumenttoanothermethod,suchaswhatactionshouldbetakenwhensomeoneclicksabutton.Lambdaexpressionsenableyoutodothis,totreatfunctionalityasmethodargument,orcodeasdata.</p><p>Theprevioussection,AnonymousClasses,showsyouhowtoimplementabaseclasswithoutgivingitaname.Althoughthisisoftenmoreconcisethananamedclass,forclasseswithonlyonemethod,evenananonymousclassseemsabitexcessiveandcumbersome.Lambdaexpressionsletyouexpressinstancesofsinglemethodclassesmorecompactly.</p><p>Thissectioncoversthefollowingtopics:</p><p>IdealUseCaseforLambdaExpressionsApproach1:CreateMethodsThatSearchforMembersThatMatchOneCharacteristicApproach2:CreateMoreGeneralizedSearchMethodsApproach3:SpecifySearchCriteriaCodeinaLocalClassApproach4:SpecifySearchCriteriaCodeinanAnonymousClassApproach5:SpecifySearchCriteriaCodewithaLambdaExpressionApproach6:UseStandardFunctionalInterfaceswithLambdaExpressionsApproach7:UseLambdaExpressionsThroughoutYourApplicationApproach8:UseGenericsMoreExtensivelyApproach9:UseAggregateOperationsThatAcceptLambdaExpressionsasParameters</p><p>LambdaExpressionsinGUIApplicationsSyntaxofLambdaExpressionsAccessingLocalVariablesoftheEnclosingScopeTargetTyping</p><p>TargetTypesandMethodArgumentsSerialization</p><p>IdealUseCaseforLambdaExpressions</p><p>Supposethatyouarecreatingasocialnetworkingapplication.Youwanttocreateafeaturethatenablesanadministratortoperformanykindofaction,suchassendingamessage,onmembersofthesocialnetworkingapplicationthatsatisfycertaincriteria.Thefollowingtabledescribesthisusecaseindetail:</p><p>Field Description</p><p>Name Performactiononselectedmembers</p><p>PrimaryActor Administrator</p><p>Preconditions Administratorisloggedintothesystem.</p><p>Postconditions Actionisperformedonlyonmembersthatfitthespecifiedcriteria.</p><p>MainSuccessScenario</p><p>1. Administratorspecifiescriteriaofmembersonwhichtoperformacertainaction.2. Administratorspecifiesanactiontoperformonthoseselectedmembers.3. AdministratorselectstheSubmitbutton.4. Thesystemfindsallmembersthatmatchthespecifiedcriteria.5. Thesystemperformsthespecifiedactiononallmatchingmembers.</p><p>Extensions 1a.AdministratorhasanoptiontopreviewthosememberswhomatchthespecifiedcriteriabeforeheorshespecifiestheactiontobeperformedorbeforeselectingtheSubmitbutton.</p><p>FrequencyofOccurrence</p><p>Manytimesduringtheday.</p><p>SupposethatmembersofthissocialnetworkingapplicationarerepresentedbythefollowingPersonclass:</p><p>Documentation</p><p>TheJavaTutorials</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 2/10</p><p>publicclassPerson{</p><p>publicenumSex{</p><p>MALE,FEMALE</p><p>}</p><p>Stringname</p><p>LocalDatebirthday</p><p>Sexgender</p><p>StringemailAddress</p><p>publicintgetAge(){</p><p>//...</p><p>}</p><p>publicvoidprintPerson(){</p><p>//...</p><p>}</p><p>}</p><p>SupposethatthemembersofyoursocialnetworkingapplicationarestoredinaListinstance.</p><p>Thissectionbeginswithanaiveapproachtothisusecase.Itimprovesuponthisapproachwithlocalandanonymousclasses,andthenfinisheswithanefficientandconciseapproachusinglambdaexpressions.FindthecodeexcerptsdescribedinthissectionintheexampleRosterTest.</p><p>Approach1:CreateMethodsThatSearchforMembersThatMatchOneCharacteristic</p><p>Onesimplisticapproachistocreateseveralmethodseachmethodsearchesformembersthatmatchonecharacteristic,suchasgenderorage.Thefollowingmethodprintsmembersthatareolderthanaspecifiedage:</p><p>publicstaticvoidprintPersonsOlderThan(Listroster,intage){</p><p>for(Personp:roster){</p><p>if(p.getAge()&gt;=age){</p><p>p.printPerson()</p><p>}</p><p>}</p><p>}</p><p>Note:AListisanorderedCollection.Acollectionisanobjectthatgroupsmultipleelementsintoasingleunit.Collectionsareusedtostore,retrieve,manipulate,andcommunicateaggregatedata.Formoreinformationaboutcollections,seetheCollectionstrail.</p><p>Thisapproachcanpotentiallymakeyourapplicationbrittle,whichisthelikelihoodofanapplicationnotworkingbecauseoftheintroductionofupdates(suchasnewerdatatypes).SupposethatyouupgradeyourapplicationandchangethestructureofthePersonclasssuchthatitcontainsdifferentmembervariablesperhapstheclassrecordsandmeasuresageswithadifferentdatatypeoralgorithm.YouwouldhavetorewritealotofyourAPItoaccommodatethischange.Inaddition,thisapproachisunnecessarilyrestrictivewhatifyouwantedtoprintmembersyoungerthanacertainage,forexample?</p><p>Approach2:CreateMoreGeneralizedSearchMethods</p><p>ThefollowingmethodismoregenericthanprintPersonsOlderThanitprintsmemberswithinaspecifiedrangeofages:</p><p>publicstaticvoidprintPersonsWithinAgeRange(</p><p>Listroster,intlow,inthigh){</p><p>for(Personp:roster){</p><p>if(low</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 3/10</p><p>}</p><p>}</p><p>ThismethodcheckseachPersoninstancecontainedintheListparameterrosterwhetheritsatisfiesthesearchcriteriaspecifiedintheCheckPersonparametertesterbyinvokingthemethodtester.test.Ifthemethodtester.testreturnsatruevalue,thenthemethodprintPersonsisinvokedonthePersoninstance.</p><p>Tospecifythesearchcriteria,youimplementtheCheckPersoninterface:</p><p>interfaceCheckPerson{</p><p>booleantest(Personp)</p><p>}</p><p>ThefollowingclassimplementstheCheckPersoninterfacebyspecifyinganimplementationforthemethodtest.ThismethodfiltersmembersthatareeligibleforSelectiveServiceintheUnitedStates:itreturnsatruevalueifitsPersonparameterismaleandbetweentheagesof18and25:</p><p>classCheckPersonEligibleForSelectiveServiceimplementsCheckPerson{</p><p>publicbooleantest(Personp){</p><p>returnp.gender==Person.Sex.MALE&amp;&amp;</p><p>p.getAge()&gt;=18&amp;&amp;</p><p>p.getAge()p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 4/10</p><p>booleantest(Personp)</p><p>}</p><p>Thisisaverysimpleinterface.It'safunctionalinterfacebecauseitcontainsonlyoneabstractmethod.Thismethodtakesoneparameterandreturnsabooleanvalue.Themethodissosimplethatitmightnotbeworthittodefineoneinyourapplication.Consequently,theJDKdefinesseveralstandardfunctionalinterfaces,whichyoucanfindinthepackagejava.util.function.</p><p>Forexample,youcanusethePredicateinterfaceinplaceofCheckPerson.Thisinterfacecontainsthemethodbooleantest(Tt):</p><p>interfacePredicate{</p><p>booleantest(Tt)</p><p>}</p><p>TheinterfacePredicateisanexampleofagenericinterface.(Formoreinformationaboutgenerics,seetheGenerics(Updated)lesson.)Generictypes(suchasgenericinterfaces)specifyoneormoretypeparameterswithinanglebrackets().Thisinterfacecontainsonlyonetypeparameter,T.Whenyoudeclareorinstantiateagenerictypewithactualtypearguments,youhaveaparameterizedtype.Forexample,theparameterizedtypePredicateisthefollowing:</p><p>interfacePredicate{</p><p>booleantest(Persont)</p><p>}</p><p>ThisparameterizedtypecontainsamethodthathasthesamereturntypeandparametersasCheckPerson.booleantest(Personp).Consequently,youcanusePredicateinplaceofCheckPersonasthefollowingmethoddemonstrates:</p><p>publicstaticvoidprintPersonsWithPredicate(</p><p>Listroster,Predicatetester){</p><p>for(Personp:roster){</p><p>if(tester.test(p)){</p><p>p.printPerson()</p><p>}</p><p>}</p><p>}</p><p>Asaresult,thefollowingmethodinvocationisthesameaswhenyouinvokedprintPersonsinApproach3:SpecifySearchCriteriaCodeinaLocalClasstoobtainmemberswhoareeligibleforSelectiveService:</p><p>printPersonsWithPredicate(</p><p>roster,</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 5/10</p><p>if(tester.test(p)){</p><p>block.accept(p)</p><p>}</p><p>}</p><p>}</p><p>Asaresult,thefollowingmethodinvocationisthesameaswhenyouinvokedprintPersonsinApproach3:SpecifySearchCriteriaCodeinaLocalClasstoobtainmemberswhoareeligibleforSelectiveService.Thelambdaexpressionusedtoprintmembersishighlighted:</p><p>processPersons(</p><p>roster,</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()p.printPerson()</p><p>)</p><p>Whatifyouwanttodomorewithyourmembers'profilesthanprintingthemout.Supposethatyouwanttovalidatethemembers'profilesorretrievetheircontactinformation?Inthiscase,youneedafunctionalinterfacethatcontainsanabstractmethodthatreturnsavalue.TheFunctioninterfacecontainsthemethodRapply(Tt).Thefollowingmethodretrievesthedataspecifiedbytheparametermapper,andthenperformsanactiononitspecifiedbytheparameterblock:</p><p>publicstaticvoidprocessPersonsWithFunction(</p><p>Listroster,</p><p>Predicatetester,</p><p>Functionmapper,</p><p>Consumerblock){</p><p>for(Personp:roster){</p><p>if(tester.test(p)){</p><p>Stringdata=mapper.apply(p)</p><p>block.accept(data)</p><p>}</p><p>}</p><p>}</p><p>ThefollowingmethodretrievestheemailaddressfromeachmembercontainedinrosterwhoiseligibleforSelectiveServiceandthenprintsit:</p><p>processPersonsWithFunction(</p><p>roster,</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()p.getEmailAddress(),</p><p>email&gt;System.out.println(email)</p><p>)</p><p>Approach8:UseGenericsMoreExtensively</p><p>ReconsiderthemethodprocessPersonsWithFunction.Thefollowingisagenericversionofitthataccepts,asaparameter,acollectionthatcontainselementsofanydatatype:</p><p>publicstaticvoidprocessElements(</p><p>Iterablesource,</p><p>Predicatetester,</p><p>Functionmapper,</p><p>Consumerblock){</p><p>for(Xp:source){</p><p>if(tester.test(p)){</p><p>Ydata=mapper.apply(p)</p><p>block.accept(data)</p><p>}</p><p>}</p><p>}</p><p>ToprinttheemailaddressofmemberswhoareeligibleforSelectiveService,invoketheprocessElementsmethodasfollows:</p><p>processElements(</p><p>roster,</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()p.getEmailAddress(),</p><p>email&gt;System.out.println(email)</p><p>)</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 6/10</p><p>Thismethodinvocationperformsthefollowingactions:</p><p>1. Obtainsasourceofobjectsfromthecollectionsource.Inthisexample,itobtainsasourceofPersonobjectsfromthecollectionroster.Noticethatthecollectionroster,whichisacollectionoftypeList,isalsoanobjectoftypeIterable.</p><p>2. FiltersobjectsthatmatchthePredicateobjecttester.Inthisexample,thePredicateobjectisalambdaexpressionthatspecifieswhichmemberswouldbeeligibleforSelectiveService.</p><p>3. MapseachfilteredobjecttoavalueasspecifiedbytheFunctionobjectmapper.Inthisexample,theFunctionobjectisalambdaexpressionthatreturnstheemailaddressofamember.</p><p>4. PerformsanactiononeachmappedobjectasspecifiedbytheConsumerobjectblock.Inthisexample,theConsumerobjectisalambdaexpressionthatprintsastring,whichistheemailaddressreturnedbytheFunctionobject.</p><p>Youcanreplaceeachoftheseactionswithanaggregateoperation.</p><p>Approach9:UseAggregateOperationsThatAcceptLambdaExpressionsasParameters</p><p>ThefollowingexampleusesaggregateoperationstoprinttheemailaddressesofthosememberscontainedinthecollectionrosterwhoareeligibleforSelectiveService:</p><p>roster</p><p>.stream()</p><p>.filter(</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()p.getEmailAddress())</p><p>.forEach(email&gt;System.out.println(email))</p><p>ThefollowingtablemapseachoftheoperationsthemethodprocessElementsperformswiththecorrespondingaggregateoperation:</p><p>processElementsAction AggregateOperation</p><p>Obtainasourceofobjects Streamstream()</p><p>FilterobjectsthatmatchaPredicateobject Streamfilter(Predicate</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 7/10</p><p>Acommaseparatedlistofformalparametersenclosedinparentheses.TheCheckPerson.testmethodcontainsoneparameter,p,whichrepresentsaninstanceofthePersonclass.</p><p>Note:Youcanomitthedatatypeoftheparametersinalambdaexpression.Inaddition,youcanomittheparenthesesifthereisonlyoneparameter.Forexample,thefollowinglambdaexpressionisalsovalid:</p><p>p&gt;p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()</p><p>Abody,whichconsistsofasingleexpressionorastatementblock.Thisexampleusesthefollowingexpression:</p><p>p.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge(){</p><p>returnp.getGender()==Person.Sex.MALE</p><p>&amp;&amp;p.getAge()&gt;=18</p><p>&amp;&amp;p.getAge()System.out.println(email)</p><p>Notethatalambdaexpressionlooksalotlikeamethoddeclarationyoucanconsiderlambdaexpressionsasanonymousmethodsmethodswithoutaname.</p><p>Thefollowingexample,Calculator,isanexampleoflambdaexpressionsthattakemorethanoneformalparameter:</p><p>publicclassCalculator{</p><p>interfaceIntegerMath{</p><p>intoperation(inta,intb)</p><p>}</p><p>publicintoperateBinary(inta,intb,IntegerMathop){</p><p>returnop.operation(a,b)</p><p>}</p><p>publicstaticvoidmain(String...args){</p><p>CalculatormyApp=newCalculator()</p><p>IntegerMathaddition=(a,b)&gt;a+b</p><p>IntegerMathsubtraction=(a,b)&gt;ab</p><p>System.out.println("40+2="+</p><p>myApp.operateBinary(40,2,addition))</p><p>System.out.println("2010="+</p><p>myApp.operateBinary(20,10,subtraction))</p><p>}</p><p>}</p><p>ThemethodoperateBinaryperformsamathematicaloperationontwointegeroperands.TheoperationitselfisspecifiedbyaninstanceofIntegerMath.Theexampledefinestwooperationswithlambdaexpressions,additionandsubtraction.Theexampleprintsthefollowing:</p><p>40+2=42</p><p>2010=10</p><p>AccessingLocalVariablesoftheEnclosingScope</p><p>Likelocalandanonymousclasses,lambdaexpressionscancapturevariablestheyhavethesameaccesstolocalvariablesoftheenclosingscope.However,unlikelocalandanonymousclasses,lambdaexpressionsdonothaveanyshadowingissues(seeShadowingformoreinformation).Lambdaexpressionsarelexicallyscoped.Thismeansthattheydonotinheritanynamesfromasupertypeorintroduceanewlevelofscoping.Declarationsinalambdaexpressionareinterpretedjustastheyareintheenclosingenvironment.Thefollowingexample,LambdaScopeTest,demonstratesthis:</p><p>importjava.util.function.Consumer</p></li><li><p>5/3/2015 LambdaExpressions(TheJavaTutorials&gt;LearningtheJavaLanguage&gt;ClassesandObjects)</p><p>https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#approach1 8/10</p><p>publicclassLambdaScopeTest{</p><p>publicintx=0</p><p>classFirstLevel{</p><p>publicintx=1</p><p>voidmethodInFirstLevel(intx){</p><p>//Thefollowingstatementcausesthecompilertogenerate</p><p>//theerror"localvariablesreferencedfromalambdaexpression</p><p>//mustbefinaloreffectivelyfinal"instatementA:</p><p>//</p><p>//x=99</p><p>ConsumermyConsumer=(y)&gt;</p><p>{</p><p>System.out.println("x="+x)//StatementA</p><p>System.out.println("y="+y)</p><p>System.out.println("this.x="+this.x)</p><p>System.out.println("LambdaScopeTest.this.x="+</p><p>LambdaScopeTest.this.x)</p><p>}</p><p>myConsumer.accept(x)</p><p>}</p><p>}</p><p>publicstaticvoidmain(String...args){</p><p>LambdaScopeTestst=newLambdaScopeTest()</p><p>LambdaScopeTest.FirstLevelfl=st.newFirstLevel()</p><p>fl.methodInFirstLevel(23)</p><p>}</p><p>}</p><p>Thisexamplegeneratesthefollowingoutput:</p><p>x=23</p><p>y=23</p><p>this.x=1</p><p>LambdaScopeTest.this.x=0</p><p>IfyousubstitutetheparameterxinplaceofyinthedeclarationofthelambdaexpressionmyConsumer,thenthecompilergeneratesanerror:</p><p>ConsumermyConsumer=(x)&gt;{</p><p>//...</p><p>}</p><p>Thecompilergeneratestheerror"variablexisalreadydefinedinmethodmethodInFirstLevel(int)"becausethelambdaexpressiondoesnotintroduceanewlevelofscoping.Consequently,youcandirectlyaccessfields,methods,andlocalvariablesoftheenclosingscope.Forexample,thelambdaexpressiondirectlyaccessestheparameterxofthemethodmethodInFirstLevel.Toaccessvariablesintheenclosingclass,usethekeywordthis.Inthisexample,this.xreferstothemembervariableFirstLevel....</p></li></ul>