lambda expressions (the java™ tutorials _ learning the java language _ classes and objects)
DESCRIPTION
Lamda Has been introduced to Java 8 Version. Here is an overviewTRANSCRIPT
-
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