应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

Java基础Lambda表达式就是这么简单!

  Lambda表达式是Java8中新增的特性,lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。在以前定义的方法中,只能将基本类型或者引用类型的变量作为方法参数,在Java8以后可以将一个代码片段作为方法参数。Lambda表达式入门
  在集合中Java为开发者提供了遍历集合的简洁方式,如下例所示:packagecn。bytecollege;importjava。util。List;importjava。util。ArrayList;publicclassLambdaDemo{publicstaticvoidmain(String〔〕args){ListStringlistnewArrayList();list。add(张三);list。add(李四);list。add(王五);list。forEach(eSystem。out。println(e));}}
  在上面的示例中,调用了list对象的foreach方法,从程序可以看出,传入foreach的并不是一个变量,而是一段代码,这就是Lambda表达式。从上面的语法可以看出,Lambda表达式的主要作用就是代替匿名内部类的烦琐语法。
  Lambda由3部分组成:形参列表:形参列表允许省略形参的数据类型,如果形参列表中有且只有1个参数,可以省略形参列表的括号箭头函数:必须有横线和大于号组成代码块。如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号。
  下面,通过示例来学习Lambda的写法:表达式只有1个参数(a){System。out。print(a);}表达式可以简写为a{System。out。print(a);}如果代码块中只有1条语句,可以省略大括号aSystem。out。print(a)函数式接口
  Lambda表达式的目标类型必须是函数式接口,所谓函数式接口代表只包含一个抽象方法的接口,函数式接口可以包含多个默认方法、类方法,但是只能声明一个抽象方法。
  如果采用匿名内部类语法来创建函数式接口的实例,则只需要实现一个抽象方法,在这种情况下可采用Lambda表达式来创建对象。
  注意:Java8专门为函数式接口提供了FunctionalInterface注解,该注解通常放在接口定义前,该注解对程序功能没有任何作用,它的作用是用于告诉编译器执行更严格的检查,检查该接口必须是函数式接口,否则编译器出错。
  Lambda表达式的结果就是被作为对象,程序中晚期可以使用Lambda表达式进行赋值,例如在多线程Thread类的构造器中可以传入Runnable接口的子类对象。查看Runnable接口发现,该接口也被声明为一个函数式接口:FunctionalInterfacepublicinterfaceRunnable{publicabstractvoidrun();}
  所以,就可以使用Lambda表达式来创建线程:packagecn。bytecollege;publicclassThreadLambdaDemo{publicstaticvoidmain(String〔〕args){ThreadthreadnewThread((){for(inti0;i10;i){System。out。println(i);}});thread。start();}}
  Lambda表达式实现的是匿名方法因此它只能实现特定函数式接口中的唯一方法。这意味着Lambda表达式有如下两个限制。Lambda表达式的目标类型必须是明确的函数式接口。Lambda表达式只能为函数式接口创建对象。Lambda表达式只能实现一个方法,因此它只能为只有一个抽象方法的接口(函数式接口)创建对象。
  下面定义一个函数式接口深入学习Lambda表达式packagecn。bytecollege;函数式接口只能有一个抽象方法,并且要使用FunctionalInterface声明FunctionalInterfacepublicinterfaceConsumer{intadd(inta,intb);}
  定义一个方法,方法参数是Consumer接口:packagecn。bytecollege;publicclassMyTest{publicstaticinttest(Consumerconsumer){inta5;intb4;returnconsumer。add(a,b);}publicstaticvoidmain(String〔〕args){intktest((a,b){returnab;});System。out。println(k);}}
  在上例中定义了一个函数式接口,在测试类的test方法传入了接口并调用了Consumer接口的add方法,需要注意的是,此时add方法并没有方法实现,在main方法中调用了test,并将一段代码(即add方法的实现)也就是lambda表达式当做参数传入了test方法。换句话说在上例中使用了lambda表达替代了烦琐的匿名内部类。对比下面的代码就可以看出Lambda表达式的独到之处。packagecn。bytecollege;publicclassMyTest{publicstaticinttest(Consumerconsumer){inta5;intb4;returnconsumer。add(a,b);}publicstaticvoidmain(String〔〕args){intktest(newConsumer(){Overridepublicintadd(inta,intb){returnab;}});System。out。println(k);}}
  从前面的程序可以看出Lambda表达式的使用离不开函数式接口,通常函数式接口中有且只能有1个抽象方法,这样使用Lambda表达式时也就明确了是哪个抽象方法的实现,如果接口中出现了多个抽象方法,那么就不能在接口上使用FunctionInterface注解,会编译出错。因此,Java8在java。util。function包中预定义了大量函数式接口,通常情况下这些接口完全可以满足开发需要:XxxFunction这类接口中通常包含一个apply()抽象方法,该方法对参数进行处理、转换(apply()方法的处理逻辑由Lambda表达式来实现),然后返回一个新的值。该函数式接口通常用于对指定数据进行转换处理。XxxConsumer这类接口中通常包含一个accept()抽象方法,该方法与XxxFunction接口中的apply()方法基本相似,也负责对参数进行处理,只是该方法不会返回处理结果。XxxxPredicate这类接口中通常包含一个test()抽象方法,该方法通常用来对参数进行某种判断test()方法的判断逻辑由Lambda表达式来实现),然后返回一个boolean值。该接口通常用于判断参数是否满足特定条件,经常用于进行筛滤数据。XxxSupplier这类接口中通常包含一个getAsXxx()抽象方法,该方法不需要输入参数,该方法会按某种逻辑算法(getAsXxx()方法的逻辑算法由Lambda表达式来实现)返回一个数据。综上所述,不难发现Lambda表达式的本质很简单,就是使用简洁的语法来创建函数式接口的实例这种语法避免了匿名内部类的烦琐。
  下面在程序中示范上述接口的使用:packagecn。bytecollege。lambda;importjava。util。function。Function;数据转换authorMR。WpublicclassCastUtil{定义方法将Object类型转换为String类型paramfunctionparamoreturnpublicstaticStringcastToString(FunctionObject,Stringfunction,Integera){returnfunction。apply(a);}}
  在上面的CastUtil类中定义了castToString,在该方法中第一个参数是一个Java8预定义的函数式接口,在方法内调用了Function接口的apply()方法,作用是将任意类型转换成String。但是此时这个方法并没有方法的实现,需要在调用此方法时传入方法的实现。packagecn。bytecollege。lambda;importjava。util。function。Function;publicclassTest{publicstaticvoidmain(String〔〕args){Integera10010;使用Lambda表达式,此时castToString方法的第一个参数就是Function函数式接口apply()的实现StringsCastUtil。castToString((o){returnString。valueOf(o);},a);System。out。println(s);}}
  在测试类中,调用了CastUtil的castToString()方法,并传入了Lambda表达式,以此Lambda表达式作为apply()方法的实现,在表达式中使用了String。valueOf()方法将对象转换成String类型。方法引用与构造器引用
  前面已经介绍过,如果Lambda表达式的代码块只有一条代码,程序就可以省略Lambda表达式中代码块的花括号。不仅如此,如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器引用。方法引用和构造器引用可以让Lambda表达式的代码块更加简洁。方法引用和构造器引用都需要使用两个英文冒号。
  Lambda表达式支持如下表所示的几种引用方式。引用类方法
  下面的示例将演示类方法的引用,首先定义一个函数式接口,接口中定义抽象方法castToString(),该方法的作用是将一个对象转换成String对象。packagecn。bytecollege。lambda;FunctionalInterfacepublicinterfaceFunctionT,R{RcastToString(Tt);}
  在String的学习中可以知道,String类有提供了类方法valueOf(Objecto),该方法可以将任意对象转换成String类型,因此可以使用该方法作为Lambda表达式的实现代码:packagecn。bytecollege。lambda;publicclassRefTest{publicstaticvoidmain(String〔〕args){FunctionObject,Stringfunctiona{returnString。valueOf(a);};System。out。println(function。castToString(张三));}}
  在上面的代码中,创建了Lambda表达式作为了Function接口中castToString()方法的实现。在Lambda表达式中调用了String。valueOf()方法来进行对象到字符串的转换,在代码第8行调用了function接口的castToString()方法,实际上调用了就是代码第5行创建的Lambda表达式。
  上面的Lambda表达式的代码块只有一行调用类方法的代码,因此可以使用如下方法引用进行替换。代码如下:packagecn。bytecollege。lambda;publicclassRefTest{publicstaticvoidmain(String〔〕args){FunctionObject,StringfunctionString::valueOf;System。out。println(function。castToString(张三));}}
  对于上面的类方法的引用,也就是调用了String类的valueOf()方法来实现Function函数式接口中唯一抽象方法。当调用castToString()方法时,调用参数将会传给String类的valueOf()类方法。引用对象的实例方法
  下面演示第二种方法引用,引用对象的实例方法,首先使用Lambda表达式创建一个Function接口的子类对象:FunctionObject,Stringfunctionoo。toString();
  上面的Lambda表达式只有一条语句,因此省略了该代码的花括号。
  接下来程序调用function对象的castToString()方法:packagecn。bytecollege。lambda;publicclassRefTest{publicstaticvoidmain(String〔〕args){FunctionObject,Stringfunctionoo。toString();System。out。println(function。castToString(100));}}
  上面的程序调用了function对象的castToString()方法时,由于function对象是Lambda表达式创建,castToString()方法的执行体就是Lambda表达式的代码部分,因此上面的程序输出了100。
  上面的Lambda表达式代码只有一行,且调用了对象的o的toString()实例方法。因此代码可以进行如下替换:packagecn。bytecollege。lambda;publicclassRefTest{publicstaticvoidmain(String〔〕args){FunctionObject,StringfunctionObject::toString;System。out。println(function。castToString(100));}}
  上面的Lambda表达式的代码只有一条语句,因此省略了代码块的花括号;而且由于表达式实现的castToString方法需要返回值,因此Lambda表达会将这行代码的值作为返回值。此时就可以使用方法引用进行替换,直接引用Object的toString()方法作为Lambda表达式的代码块。其中Function接口的castToString方法有个参数,当执行Lambda表达式代码块时,会自动调用传入参数的toString()方法。引用构造器
  下面的实例将演示如何引用构造器,首先定义函数式接口:packagecn。bytecollege。lambda;FunctionalInterfacepublicinterfaceMyInterface{StringBuilderget(Strings);}
  该函数式接口包含了一个get()抽象方法,该方法的作用是使用String对象生成一个StringBuilder对象,接着使用Lambda表达式创建一个MyInterface的对象:packagecn。bytecollege。lambda;publicclassRefTest3{publicstaticvoidmain(String〔〕args){MyInterfacemyInterface(s)newStringBuilder(s);StringBuildersbmyInterface。get(张三);}}
  上面的代码调用了myInterface对象的get()方法时,由于该对象是Lambda表达式创建的,因此get()方法执行体就是Lambda表达式的代码块部分,即执行体就是执行newStringBuilder(a)语句,并将这条语句的值作为方法的返回值。因此上面代码中Lambda表达式的代码可以进行如下替换:packagecn。bytecollege。lambda;publicclassRefTest3{publicstaticvoidmain(String〔〕args){MyInterfacemyInterfaceStringBuilder::new;StringBuildersbmyInterface。get(张三);}}
  对于上面的构造器引用,也就是调用StringBuilder类的构造方法来实现MyInteface函数式接口中唯一的抽象方法,当调用MyInterface接口的get()方法时,调用参数会传给StringBuilder构造器,从上面的程序中可以看出,调用myInterface对象的get()方法时,实际只传入了一个String类型的参数,这个String类型的参数会被传给StringBuilder的构造器。Lambda表达式和匿名内部类的联系和区别
  从前面介绍可以看出,Lambda表达式是匿名内部类的一种简化,因此它可以部分取代匿名内部类的作用,Lambda表达式与匿名内部类存在如下相同点。Lambda表达式与匿名内部类一样,都可以直接访问effectivelyfinal的局部变量,以及外部类的成员变量(包括实例变量和类变量)。Lambda表达式创建的对象与匿名内部类生成的对象一样,都可以直接调用从接口中继承的默认方法。
  首先创建函数式接口:packagecn。bytecollege。ano;FunctionalInterfacepublicinterfaceDisplay{intadd(inta,intb);defaultvoidprint(){System。out。println(Hello!);}}packagecn。bytecollege。ano;publicclassLambdaTest{privateintage18;privatestaticStringnameByte科技;publicvoidtest(){StringbookJava编程思想;Displaydisplay(a,b){访问外部类的实例变量System。out。println(age);访问外部类的类变量System。out。println(name);访问局部变量System。out。println(book);returnab;};调用display对象从接口继承的默认方法display。print();bookJava核心技术卷;System。out。println(display。add(1,2));}}
  创建测试类:packagecn。bytecollege。ano;publicclassTest{publicstaticvoidmain(String〔〕args){LambdaTesttestnewLambdaTest();test。test();}}
  上面的程序使用Lambda表达式创建了一个Display接口的对象,Lambda表达式分别访问了外部类的实例变量,类变量从这些来看Lambda表达式的代码块和匿名内部类的方法体是相同的。
  和匿名内部类相似,由于Lambda表达式访问了了book局部变量,因此该局部变量相当于有一个隐式的final修饰,不允许对book局部变量重新赋值。
  当程序使用Lambda表达式创建了Display的对象之后,该对象不仅可调用接口中唯一的抽象方法,也可调用接口中的默认方法。
  Lambda表达式与匿名内部类主要存在如下区别:匿名内部类可以为任意接口创建实例不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方法即可;但Lambda表达式只能为函数式接口创建实例。匿名内部类可以为抽象类甚至普通类创建实例;但Lambda表达式只能为函数式接口创建实例。匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;但Lambda表达式的代码块不允许调用接口中定义的默认方法。

明明前后只差20天,任嘉伦演的周生辰和长意,差别咋就那么大呢任嘉伦称王,天下无双。忘了在哪里看到过这样的一条评论。虽然,这说法有点夸大其词。但仔细想想,任嘉伦演过的不管是广平王李俶,还是小南辰王周生辰,都给观众留下了十……NBA盘点常规赛执教胜场1000场却没有总冠军的传奇教练教练是赢得总冠军的最重要的因素。库班,独行侠老板开篇话:记得本赛季开赛大概一个半月的时间,国王队主教练小沃顿被球队解雇,成为第一位下课的主教练。作为名宿之子,球员时代跟随……外国人在中国给长期在中国工作生活的外籍人的一些建议,值得收藏目前,中国已经成为世界东方的最大的经济体,一举一动都牵动着整个世界的经济大局,外国人来到中国找工作已经变成一种常态。多年以来,外国人到中国工作的情况,已经发生了根本的变化。……霸王龙跟狮子打架谁会赢?这种问题都写进书,这代孩子是要逆天?要论脑洞的逆天程度,谁都比不过人类幼崽,孩子经常问的不少问题,让我这个老母亲哑口无言,完全没办法从科学角度去回答。比如他喜欢一切打架厉害的生物,就时不时过来问我:妈妈,恐龙里面……心脑血管疾病的营养调理,大家必须知道心脑血管疾病的病理基础是动脉粥样硬化,可发生在主动脉、冠状动脉、脑动脉、肢体动脉、肾动脉等处。可使动脉内膜有黄色斑或斑块沉着(内含胆固醇、胆固醇酯,甘油三酯等),并有内膜炎症、……飞撞飞踹!一回合伤俩!科尔怒喷斯玛特你这是故意伤人独行侠和马刺上演绝杀好戏,圈主没安排上头条湖人又一次大败圈主也放过了这次绝佳的吐槽机会因为后台实在是太多圈友想看圈主唠嗑唠嗑勇士了,所以忍痛割爱给大伙蹲了勇士的比赛……笑星巩汉林,让国足再次成为笑话最近几天关于著名笑星巩汉林和男足之间的骂战频繁登上热搜,再加上搅屎棍董贼怂天怂地的一通乱骂,着实让吃瓜群众看了一场好戏!有人说巩汉林是一个门外汉,不懂足球就不要瞎评论!那……全球彩电销量Top15三星第1,小米第5,华为第15,国产8虽然现在小屏越来越挤占大屏的空间,比如Pad、手机、电脑等占了彩电的空间,抢走了用户的时间,但对于很多人而言,家里买一台电视还是必须的,不管看不看。所以这些年以来,虽然彩……3位知名男星塌房!为户口陪睡男大佬,2天潜规则2位女星,毁三4月16日,娱乐圈再次迎来3大丑闻瓜,两个和出轨有关,一个和没有底线有关,不得不说,现如今的娱乐圈真的是,只有想不到的,没有他们做不到的。首先第一个瓜就来自赵弈钦,被女友……又见海棠花开!快来这里邂逅济南醉美的春天!阳春三月,春光明媚,天下第一泉风景区内柳条抽芽,百花争艳。其中,有花贵妃、花中神仙之称的海棠,姿容优美,娇艳芬芳,恰在绿肥红肥时,更让人们沉醉。海棠是蔷薇科苹果属多种植物……人在低谷时,如何治愈自己?这是我听过最好的答案最近,看到一个新闻,内心久久不能平静。4月6日,湖南张家界,4名来自不同地方的游客,相约在天门山景区。在到达山顶处时,毫无预兆下,先后翻越护栏跳崖。结果,3人……再次82场全勤!科尔卢尼就是那种你在选秀中最想得到的球员直播吧4月10日讯今日NBA常规赛收官战,勇士客场157101大破开拓者。勇士主帅科尔赛后接受了采访。谈到本赛季再次82场全勤的卢尼,科尔不吝赞美之词,他说道:卢尼正是那……
深度了解,国内与国外的政策哪个对币圈影响大?有朋友要我说说加密数字货币未来走势,其实我以前都已经说过好多次了,所以打算换个方式,用多空双方利多利空消息的对比来说明,让大家有个直观的感受,但在这之前,还打算说明一下,我们判……购机预算3000元左右?这款手机或许是你的最优选【手机中国行情】买手机不能买太差的,太差的用一两年就会变卡,到时候又得换机,还要把手机里的资料导过去导过来,太过麻烦。不过话说回来,又有谁不想买旗舰呢?问题是贵埃有没有稍微便宜……颜值经济时代,如何重塑面部年轻态?抖音、朋友圈、小红书、B站发展如火如荼美妆护肤穿搭博主不计其数颜值经济时代已至大众对面部年轻态愈加重视广大求美者的需求浓缩成多快好省四个字……人民币可以买港股,澳门玩家们乐开花了很多内地大哥在澳门会比较发愁怎么兑换港币的;因为外汇管制的原因,每人每年也就只能兑换5W价值美元外汇,大哥们不可能去个旅游消费走公司账吧,所以只能找换钱党了;那么现……爱心接力!84岁患病爷爷完成现场看球心愿老人在现场看球3月17日,辽宁男篮97:71大胜宁波男篮,图为辽篮球员郭艾伦(右)与弗格。辽篮吉祥物肖肖与现场小球迷互动在恢复主客场赛制之后,辽宁男篮已经取得……开春后别急着穿卫衣,这件小香风短上衣才吃香,配裙又仙又美卫衣舒适百搭又具备不错的减龄效果,向来都很受时髦精们的欢迎,但开春不建议大家急着穿卫衣。卫衣虽然减龄,但整体上过于单薄,单穿其实很难赢得温度,比起卫衣,还是小香风短上衣更符合开……快消一周大事集锦(1月30日美邦服饰贝因美南极电商奥康搜于特快消八谈南极电商亏损一周大事贝因美朗姿股份2022年净利预计下降8489。331月30日,朗姿股份发布业绩预告称,预计2022年归属于上市公司股东的净利润为2000……梦幻唯美,即将开启成都金沙太阳节亮灯了!考古与科技跨界融合,点亮30万平方米的古蜀家园。2023成都金沙太阳节将于19日开启,灯组部分目前已基本搭建完成,并于17日晚亮灯。据悉,今年的灯组分为古蜀文明太阳崇拜和……微软发布Win11Beta预览版22621。1255和226IT之家2月10日消息,微软今天向Beta频道发布了Windows11InsiderPreviewBuild22621。1255和Build22623。1255(KB50229……震惊?一加小米OPPO正在肆无忌惮的泄露你的私人信息!现在处于假期结束、开学伊始的时间点,如果你考虑入手一加(OnePlus)、小米、OPPO手机,请你再次认真的考虑下!近日,爱丁堡大学(UniversityofEdinbu……专访流浪地球2科学团队科幻真实感背后是国家实力《中国经济周刊》记者孙冰北京报道随着国产科幻影片《流浪地球2》的票房数字屡创新高,影片中所呈现出的未来科技也引发了大众的广泛关注和热烈讨论,不少观众甚至开玩笑:这次拯救地……CCTV5拒播广东队颁奖仪式!杜锋携手三后卫复出,姚明阿联再为期一周的CBA季前赛结束了,明天CBA常规赛正式打响!比较遗憾的是,CCTV5和CCTV5没有安排直播,就连晚上卫冕冠军广东宏远对阵深圳队的揭幕战都没有安排直播,而且这场比赛……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网