JDK 8新特性 Lambda表达式

Lambda表达式介绍

当需要启动一个线程去完成任务时,通常会通过 Runnable 接口来定义任务内容,并使用 Thread 类来启动该线程。

传统匿名内部类写法如下:

publicclassDemo01LambdaIntro{

    publicstaticvoidmain(String[]args) {

        newThread(newRunnable() {

        @Override

            publicvoidrun() {

                System.out.println("新线程任务执行!");

            }

        }).start();

    }

}

由于面向对象的语法要求,首先创建一个 Runnable 接口的匿名内部类对象来指定线程要执行的任务内容,再将其交 给一个线程来启动。 

代码分析:

对于 Runnable 的匿名内部类用法,可以分析出几点内容:

1.Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心

2.为了指定 run 的方法体,不得不需要 Runnable 接口的实现类

3.为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类

4.必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错

5.而实际上,似乎只有方法体才是关键所在

Lambda体验

Lambda是一个匿名函数,可以理解为一段可以传递的代码。

Lambda表达式写法,代码如下:

借助Java 8的全新语法,上述 Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到相同的效果

publicclassDemo01LambdaIntro{

    publicstaticvoidmain(String[]args) {

        newThread(()->System.out.println("新线程任务执行!")).start();// 启动线程

    }

}

这段代码和刚才的执行效果是完全一样的,可以在JDK 8或更高的编译级别下通过。从代码的语义中可以看出:我们 启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定。 我们只需要将要执行的代码放到一个Lambda表达式中,不需要定义类,不需要创建对象。

Lambda的优点

简化匿名内部类的使用,语法更加简单。

Lambda的标准格式

Lambda省去面向对象的条条框框,Lambda的标准格式格式由3个部分组成:

(参数类型 参数名称) -> {

    代码体;

}

格式说明:

(参数类型 参数名称):参数列表

{代码体;}:方法体

-> :箭头,分隔参数列表和方法体

Lambda与方法的对比

匿名内部类

publicvoidrun() {

    System.out.println("aa");

}

Lambda

()->System.out.println("bb!")

无参数无返回值的Lambda

掌握了Lambda的语法,我们来通过一个案例熟悉Lambda的使用。

interfaceSwimmable{

        publicabstractvoidswimming();

}

packagecom.muziwk.demo01lambda;

publicclassDemo02LambdaUse{

    publicstaticvoidmain(String[]args) {

        goSwimming(newSwimmable() {

            @Override

            publicvoidswimming() {

                System.out.println("匿名内部类游泳");

        }

    });

        goSwimming(()->{

            System.out.println("Lambda游泳");

        });

}

    publicstaticvoidgoSwimming(Swimmableswimmable) {

        swimmable.swimming();

}

有参数有返回值的Lambda

下面举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:

public abstract int compare(T o1, T o2);

当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。

传统写法

如果使用传统的代码对 ArrayList 集合进行排序,写法如下:

publicclassPerson{

privateStringname;

privateintage;

privateintheight;

// 省略其他

}

packagecom.muziwk.demo01lambda;

importjava.util.ArrayList;

importjava.util.Arrays;

importjava.util.Collections;

importjava.util.Comparator;

publicclassDemo03LambdaUse{

publicstaticvoidmain(String[]args) {

ArrayList<Person>persons=newArrayList<>();

persons.add(newPerson("刘德华",58,174));

persons.add(newPerson("张学友",58,176));

persons.add(newPerson("刘德华",54,171));

persons.add(newPerson("黎明",53,178));


Collections.sort(persons,newComparator<Person>() {

@Override

publicintcompare(Persono1,Persono2) {

    returno1.getAge()-o2.getAge();

    }

       });


for(Personperson:persons) {

    System.out.println(person);

       }

    }

}

这种做法在面向对象的思想中,似乎也是“理所当然”的。其中 Comparator 接口的实例(使用了匿名内部类)代表 了“按照年龄从小到大”的排序规则。

Lambda写法

packagecom.muziwk.demo01lambda;

importjava.util.ArrayList;

importjava.util.Arrays;

importjava.util.Collections;

importjava.util.Comparator;

publicclassDemo03LambdaUse{

publicstaticvoidmain(String[]args) {

ArrayList<Person>persons=newArrayList<>();

persons.add(newPerson("刘德华",58,174));

persons.add(newPerson("张学友",58,176));

persons.add(newPerson("刘德华",54,171));

persons.add(newPerson("黎明",53,178));


Collections.sort(persons, (o1,o2)->{

      returno1.getAge()-o2.getAge();

   });

for(Personperson:persons) {

    System.out.println(person);

   }

System.out.println("-----------------");


List<Integer>list=Arrays.asList(11,22,33,44);

    list.forEach(newConsumer<Integer>() {

@Override

publicvoidaccept(Integerinteger) {

System.out.println(integer);

           }

         });

System.out.println("-----------------");


list.forEach((s)->{

        System.out.println(s);

    });

   }

}

小结

以后我们调用方法时,看到参数是接口就可以考虑使用Lambda表达式,Lambda表达式相当于是对接口中抽象方法的重 写

Lambda省略格式

在Lambda标准格式的基础上,使用省略写法的规则为:

小括号内参数的类型可以省略

如果小括号内有且仅有一个参数,则小括号可以省略

如果大括号内有且仅有一个语句,可以同时省略大括号、return关键字及语句分号

(int a) -> {

    return new Person();

}

省略后

a -> new Person()

Lambda的前提条件

Lambda的语法非常简洁,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意:

方法的参数或局部变量类型必须为接口才能使用Lambda

接口中有且仅有一个抽象方法

函数式接口

函数式接口在Java中是指:有且仅有一个抽象方法的接口

函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以 适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

FunctionalInterface注解

与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注 解可用于一个接口的定义上:

@FunctionalInterface

publicinterfaceOperator{

    voidmyMethod();

}

一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。不过,即 使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

Lambda和匿名内部类对比

了解Lambda和匿名内部类在使用上的区别

1.所需的类型不一样

    匿名内部类,需要的类型可以是类,抽象类,接口

Lambda表达式,需要的类型必须是接口

2.抽象方法的数量不一样

    匿名内部类所需的接口中抽象方法的数量随意 Lambda表达式所需的接口只能有一个抽象方法

3.实现原理不同

    匿名内部类是在编译后会形成class Lambda表达式是在程序运行的时候动态生成class

小结

当接口中只有一个抽象方法时,建议使用Lambda表达式,其他其他情况还是需要使用匿名内部类

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

推荐阅读更多精彩内容