最通俗易懂的讲解:lambda表达式

Java8发布已经有一段时间了,这次发布的改动比较大,很多人将这次改动与Java5的升级相提并论。Java8其中一个很重要的新特性就是lambda表达式,允许我们将行为传到函数中。想想看,在Java8 之前我们想要将行为传入函数,仅有的选择就是匿名内部类。

Java8发布以后,lambda表达式将大量替代匿名内部类的使用,简化代码的同时,更突出了原来匿名内部类中最重要的那部分包含真正逻辑的代码。尤其是对于做数据的同学来说,当习惯使用类似scala之类的函数式编程语言以后,体会将更加深刻。现在我们就来看看Java8中lambda表达式的一些常见写法。

lambda体中调用方法的参数列表和返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致。

一、替代匿名内部类

lambda表达式用的最多的场合就是替代匿名内部类,实现Runnable接口是匿名内部类的经典例子。lambda表达式的功能相当强大,用()->就可以代替整个匿名内部类!

packageOSChina.Lambda;

importorg.junit.Test;

importjava.util.Comparator;

importjava.util.function.Consumer;

importjava.util.function.Function;

importjava.util.function.Predicate;

importjava.util.function.Supplier;

publicclassTest1{

publicstaticvoidmain(String[] args){

Runnable runnable =newRunnable() {

@Override

publicvoidrun(){

System.out.println("普通,线程启动");

}

};

runnable.run();

test2();

test3();

test4();

test5();

}

//无参数,无返回值

publicstaticvoidtest2(){

//“->”左边只有一个小括号,表示无参数,右边是Lambda体(就相当于实现了匿名内部类里面的方法了,(即就是一个可用的接口实现类了。))

Runnable runnable = ()->System.out.println("Lambda 表达式方式,线程启动");

runnable.run();

}

//有一个参数,并且无返回值

publicstaticvoidtest3(){

//这个e就代表所实现的接口的方法的参数,

Consumer consumer = e->System.out.println("Lambda 表达式方式,"+e);

consumer.accept("传入参数");

}

//有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

publicstaticvoidtest4(){

//Lambda 体中有多条语句,记得要用大括号括起来

Comparator com = (x, y) -> {

System.out.println("函数式接口");

returnInteger.compare(x, y);

};

intcompare = com.compare(100,244);

System.out.println("有两个以上的参数,有返回值,"+compare);

}

//若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写

publicstaticvoidtest5(){

//Comparator com = (x, y) -> Integer.compare(100, 244);

System.out.println("若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写,"+Integer.compare(100,244));

}

}

二、Java8四大内置函数式接口

如果使用lambda还要自己写一个接口的话太麻烦,所以Java自己提供了一些接口:

1、Consumer 消费性接口:void accept(T t);

//有一个参数,并且无返回值

publicstaticvoidtest3(){

//这个e就代表所实现的接口的方法的参数,

Consumer consumer = e->System.out.println("Lambda 表达式方式,"+e);

consumer.accept("传入参数");

}

2、Supplier供给型接口:T get();

package OSChina.Lambda;

importjava.util.ArrayList;

importjava.util.function.Supplier;

publicclassTest2{

publicstaticvoidmain(String[] args){

ArrayList res = getNumList(10,()->(int)(Math.random()*100));

System.out.println(res);

}

publicstaticArrayList getNumList(intnum, Supplier sup){

ArrayListlist=newArrayList<>();

for(inti =0; i < num; i++) {

Integer e = sup.get();

list.add(e);

}

returnlist;

}

}

3、Function 函数式接口:R apply(T t);

packageOSChina.Lambda;

importjava.util.function.Function;

publicclassTest2{

publicstatic void main(String[] args) {

String newStr = strHandler("abc",(str)->str.toUpperCase());

System.out.println(newStr);

newStr = strHandler("  abc  ",(str)->str.trim());

System.out.println(newStr);

}

publicstatic String strHandler(String str, Functionfun){

returnfun.apply(str);

}

}

4、Predicate 断言式接口:boolean test(T t);

判断一些字符串数组判断长度>2的字符串:

package OSChina.Lambda;

importjava.util.ArrayList;

importjava.util.Arrays;

importjava.util.List;

importjava.util.function.Predicate;

publicclassTest2{

publicstaticvoidmain(String[] args) {

List list = Arrays.asList("hello","jiangshuying","lambda","www","ok","q");

List ret = filterStr(list,(str)->str.length()>2);

System.out.println(ret);

}

publicstaticList filterStr(List list, Predicate pre){

ArrayList arrayList =newArrayList<>();

for(Stringstr:list){

if(pre.test(str)) {

arrayList.add(str);

}

}

returnarrayList;

}

}

三、方法引用与构造器引用

要求:实现抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!

方法引用:使用操作符“::”将类与方法分隔开来。

对象::实例方法名

类::静态方法名

类::实例方法名

举个例子:

publicstaticvoidtest9(){

Comparator comparator = (x,y)->Integer.compare(x,y);

Comparator comparator1 = Integer::compare;

intcompare = comparator.compare(1,2);

intcompare1 = comparator1.compare(1,2);

System.out.println("compare:"+compare);

System.out.println("compare1:"+compare1);

}

四、lambda表达式的一些常见用法

1、使用lambda表达式对集合进行迭代

package OSChina.Lambda;

importjava.util.Arrays;

importjava.util.List;

publicclassTest3{

publicstaticvoidmain(String[] args){

Listlist= Arrays.asList("java","c#","javascript");

//before java8

for(String str:list){

System.out.println("before java8,"+str);

}

//after java8

list.forEach(x-> System.out.println("after java8,"+x));

}

}

2、用lambda表达式实现map

map函数可以说是函数式编程里最重要的一个方法了。map的作用是将一个对象变换为另外一个。在我们的例子中,就是通过map方法将cost增加了0,05倍的大小然后输出。

package OSChina.Lambda;

importjava.util.Arrays;

importjava.util.List;

publicclassTest3{

publicstaticvoidmain(String[] args){

Listlist= Arrays.asList(10.0,20.0,30.0);

list.stream().map(x->x+x*0.05).forEach(x-> System.out.println(x));

}

}

3、用lambda表达式实现map与reduce

既然提到了map,又怎能不提到reduce。reduce与map一样,也是函数式编程里最重要的几个方法之一,map的作用是将一个对象变为另外一个,而reduce实现的则是将所有值合并为一个,请看:

package OSChina.Lambda;

importjava.util.Arrays;

importjava.util.List;

publicclassTest3{

publicstaticvoidmain(String[] args){

//before java8

List cost = Arrays.asList(10.0,20.0,30.0);

doublesum =0;

for(doubleeach:cost) {

each += each *0.05;

sum += each;

}

System.out.println("before java8,"+sum);

//after java8

Listlist= Arrays.asList(10.0,20.0,30.0);

doublesum2 =list.stream().map(x->x+x*0.05).reduce((sum1,x)->sum1+x).get();

System.out.println("after java8,"+sum2);

}

}

相信用map+reduce+lambda表达式的写法高出不止一个level。

4、filter操作

filter也是我们经常使用的一个操作。在操作集合的时候,经常需要从原始的集合中过滤掉一部分元素。

packageOSChina.Lambda;

importjava.util.Arrays;

importjava.util.List;

importjava.util.stream.Collectors;

publicclassTest3{

publicstaticvoidmain(String[] args){

List cost = Arrays.asList(10.0,20.0,30.0,40.0);

List filteredCost = cost.stream().filter(x -> x >25.0).collect(Collectors.toList());

filteredCost.forEach(x -> System.out.println(x));

}

}

5、与函数式接口Predicate配合

除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做java.util.function。它包含了很多类,用来支持Java的函数式编程。

其中一个便是Predicate,使用java.util.function.Predicate函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。Predicate接口非常适用于做过滤。

package OSChina.Lambda;

import java.lang.reflect.Array;

import java.util.Arrays;

import java.util.List;

import java.util.function.Predicate;

publicclassTest4{

publicstaticvoid filterTest(List languages, Predicate condition) {

languages.stream().filter(x -> condition.test(x)).forEach(x -> System.out.println(x +" "));

}

publicstaticvoid main(String[] args) {

List languages = Arrays.asList("Java","Python","scala","Shell","R");

filterTest(languages,x->x.startsWith("J"));//Java 

filterTest(languages,x -> x.endsWith("a"));//Java,scala 

filterTest(languages,x -> true);//Java,Python,scala,Shell,R

filterTest(languages,x -> false);//

filterTest(languages,x -> x.length() >4);//Python,scala,Shell,

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,283评论 6 530
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,947评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,094评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,485评论 1 308
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,268评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,817评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,906评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,039评论 0 285
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,551评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,502评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,662评论 1 366
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,188评论 5 356
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,907评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,304评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,563评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,255评论 3 389
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,637评论 2 370

推荐阅读更多精彩内容

  • 前言:Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。在Java Code Geek...
    糖宝_阅读 1,327评论 1 1
  • 原链接:http://www.cnblogs.com/langtianya/p/3757993.html JDK各...
    把爱放下会走更远阅读 1,125评论 0 10
  • 参考ImportNew - lemeilleur 翻译自javarevisited 用例1、用lambda表达式实...
    mulinsentt阅读 565评论 0 1
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,710评论 0 3
  • 二婆(母亲的二婶)家后院有一棵香杏树,这是一棵异于普通的杏树,它的果仁不是苦苦的那种,嚼起来清香四溢,越吃越想吃。...
    宝天曼风景阅读 741评论 0 0