Java8新特性学习之二:lambda表达式深入学习

Java8新特性学习之二:lambda表达式深入学习

前言:

前面我们已经学习lambda的入门,也感性的了解了lambda可以帮助我们解决什么问题,今天跟大家一起深入的学习如何使用、以及在哪里使用lambda表达式。如果你希望在看源码中遇到了lambda表达式不会抓狂;你希望你的代码更加优雅、简洁、或者装逼专用,咱们一起来学习。

 

  • Lambda表达式的语法
  • 在哪里使用、如何使用lambda
  • Lambda扩展

一、lambda表达式语法

如果你见过lambda表达式、或者你看过我的上一篇文章,你应该见过类似下面的代码

Thread thread = new Thread(()-> System.out.println("i am a thead ,i am running my name is "+Thread.currentThread().getName()));
thread.start();

redApples.sort((Apple a1,Apple a2)->a1.getWeight()-a2.getWeight());
Thread t = new Thread(()->{
    int a = 1;
    System.out.println(a);
});
t.start();

上面就是lambda表达式,那么lambda表达式的语法到底是怎么样的呢?使用它需要注意什么?我们从上面两个两个例子中应该能抓住一些lambda共有的特性,比如()->{}或者()->xxx。我们发现lambda表达式主要包括三个部分

1、参数列表:()里面的内容,如果为空,那么就没有参数

2、箭头:把参数列表和主体分开

3、Lambda主体:是一个表达式或者{}的内容,有返回值(返回值可能为void)

Lambda表达式的语法分下面两种:

1、(parameter)->expression

2、(parameter)->{statement;}

 

为了更加详细的掌握lambda的语法规则,下面用几个实例表示(伪代码)

//用伪代码解析lambda表达式的规则
//参数是String类型的变量,并且返回一个int,这里的retur隐藏起来了
(String s)->s.length()
//参数是Apple类型的变量,返回时一个boolean类型,return隐藏起来了
(Apple apple)->apple.getWeight() > 150
//接受两个int类型的参数,没有返回值类型,或者理解为返回void,表达式可以包括多行,需要用{}包起来
(int x,int y)->{
    System.out.println("x+y:");
    System.out.println(x+y);
}
//没有参数,返回是int类型
()->42
//接受两个apple类型,返回int类型
(Apple a1,Apple a2)->a1.getWeight()-a2.getWeight()
//return 语句是控制流语句,必须要用{}包起来,下面写法是错误的
(int a)-> return "test"+a;
//上面的正确写法应该是这样的,接受一个int类型的参数,返回一个String类型
(int a)->{return "test"+a};
//“test”是表达式,不是语句,不能用大括号包起来,这种写法是错误的。有两种修改的方式
(String s)->{"test";}
//正确写法1:不用{}:接受一个String类型的参数,返回String类型
(String s)->"test"
//正确写法2:加return
(String s)->{return  "test";}

通过上面的实例,相信大家应该都掌握了编写lambda表达式的技巧了,其实lambda表达式可以理解为一个匿名函数,将行为参数化。

二、在哪里使用、如何使用lambda

回想一下我们在前面学习的时候,在哪些场景里面使用过lambda呢?Runnable、Comparator、ApplePredicate、FruitsPredicate?当参数为这些的时候,我们用过lambda是不是?是的,不错,官网上说的是“你可以在函数式接口上使用lambda表达式”,这里有一个关键字是函数式接口,什么叫做函数式接口?下面给出它的定义

函数式接口:只定义一个抽象方法的接口

这好像跟我们刚才想的Runnable、Comparator、ApplePredicate一样,就是一个函数式接口,我们可以尝试一下在FruitsPredicate中编写两个方法,看看会发生什么。

public interface FruitsPredicate<T> {

    boolean test(T fruits);

    boolean test2(T fruits,T t2);
}

Java8新特性学习之二:lambda表达式深入学习

 会报错,没错,因为这段代码不能确定要传递哪个方法。

在哪里使用lambda这个问题,相应大家应该都知道了,就是在函数式接口中可以使用lambda表达式。那是不是我们知道了lambda表达式的语法、以及在哪里使用lambda表达式就可以了呢?答案是不够的,lambda表达式的编写还需要和函数式接口中的方法有一定的匹配规则,就是lambda表达式的参数(包括类型和个数)和返回值类型要和函数式接口的方法参数和返回值要一致。否则也是无法编译的,我们可以测试一下。

Java8新特性学习之二:lambda表达式深入学习

 这里报了一个参数不匹配的错误,因为我的函数式接口是这样子的

public interface FruitsPredicate<T> {

    boolean test(T fruits);

    //boolean test2(T fruits,T t2);
}

这里要求参数是一个对象,那么我传了两个,所以报错了

Java8新特性学习之二:lambda表达式深入学习

 这里报的错是我的函数式接口的返回值是boolean类型,而我的lambda表达式返回的int类型,也是不匹配,所以报错。好了,我相信到这里,小伙伴们应该都会使用lambda表达式了。我们有没有想过,lambda表达式是如何和函数式接口发生关联的呢?当我们使用下面的代码他是如何工作的呢?

List<Apple> heavyApples = filterFruits(inventory,(Apple apple)-> apple.getWeight() > 150);

简单的用一个流程图来描述一下:

Java8新特性学习之二:lambda表达式深入学习

三、lambda表达式扩展

1、同样的lambda表达式,不同的函数式接口

这个很简单,就是lambda表达式相同,比如都是(String name)->name +“hello world”

但是函数式接口不一样,定义两个不同的函数式接口就行啦,返回值和参数一样

2、类型推断

你有可能见过下面类似的lambda表达式的写法

redApples.sort(( a1, a2)->a1.getWeight()-a2.getWeight());
redApples.sort((Apple a1,Apple a2)->a1.getWeight()-a2.getWeight());

这两者有什么不一样吗?可以尝试下,运行的结果是一样的,这两个的唯一的区别就是第一句代码中省略了类型,这也是ok的,这是因为lambda表达式可以根据函数式接口的方法推断出参数的类型,所以以后遇到了没有类型的参数,不用大惊小怪,当然还是建议使用加上参数类型,因为这样可读性会好很多(即便省略了参数类型,性能上也没任何的提升)

3、方法引用

你或许见过下面的lambda表达式的写法

redApples.sort(comparing(Apple::getWeight));

当然comparing()方法是Comparator里面的方法,这是通过静态导入的方式,让我们使用起来就像调用本类的方法一样,这不是我们这次关注的重点,我们重点关注的是Apple::getWeight,这种方式就是方法引用。方法引用让你可以重复使用现有的方法定义,并想lambda一样传递它们,有时候,它比lambda表达式可读性更好。它的基本思想是:如果一个lambda代表的只是“直接调用这个方法”,那最好还是用名称来调用它,而不是用描述如何调用它。它是如何工作的呢?当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面,不需要使用括号,因为并没有实际调用这个方法,上面的方法引用其实就是(Apple apple)->apple.getWeight()的快捷写法。好了希望通过这篇文章可以让小伙伴们学会如何使用lambda表达式,下面我还会跟大家一起学习Stream流和Optional等java8的新特性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111219.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 永久设置python清华镜像源_清华开源镜像站怎么用

    永久设置python清华镜像源_清华开源镜像站怎么用Python配置清华镜像源1.前言使用pip安装服务器在国外的python库时,下载需要很长时间,在配置文件中设置国内镜像可以提高速度,清华镜像源就是其中之一。2.pypi镜像使用帮助网址:https://mirrors.tuna.tsinghua.edu.cn/help/pypi/3.临时配置若只是临时下载一个python库的话,则可使用以下命令进行配置:pipinstal…

    2022年10月21日
    0
  • 1040. 有几个PAT(25)- PAT乙级真题

    1040. 有几个PAT(25)- PAT乙级真题1040.有几个PAT(25)字符串APPAPT中包含了两个单词“PAT”,其中第一个PAT是第2位(P),第4位(A),第6位(T);第二个PAT是第3位(P),第4位(A),第6位(T)。现给定字符串,问一共可以形成多少个PAT?输入格式:输入只有一行,包含一个字符串,长度不超过105,只包含P、A、T三种字母。输出格式:在一行中输出给定字符串中包含多少个PAT。由于结果可能比较大,只输出对…

    2022年5月1日
    42
  • Odin Inspector 系列教程 — Hide If Attribute[通俗易懂]

    Odin Inspector 系列教程 — Hide If Attribute[通俗易懂]HideIfAttribute用于任何属性,并且可以在检查器中隐藏该属性。使用此选项可根据对象的当前状态隐藏不相关的属性。传一个属性的名称,此属性的值如果为true或者部位null,则隐藏此属性[HideIf(“IsToggled”)]publicVector3HiddenWhenToggled;[HideIf(“Som…

    2022年7月21日
    8
  • 亲测无限坐席在线客服系统源码,基于ThinkPHP的一款在线客服系统源码

    亲测无限坐席在线客服系统源码,基于ThinkPHP的一款在线客服系统源码源码简介东西没问题,和别人换的本来说是多语言带机器人翻译之类的,给了个这。。。直接一键安装的,启动两个端口就行了,安装倒是简单编号:ym270品牌:无语言:PHP大小:34.5MB类型:在线客服系统支持:pc+wap亲测无限坐席在线客服系统源码,基于ThinkPHP的一款在线客服系统源码,直接一键安装的,启动两个端口就行了。安装教程:PHP5.6+MySQL5.5+设置网站运行目录为public,配置伪静态规则为thinkphp访问/install.php安装即可亲测无限坐席

    2022年7月19日
    17
  • jmeter常见面试题_hr面试问题大全及答案

    jmeter常见面试题_hr面试问题大全及答案问题列表在项目中如何用jmeter进行http接口测试?Jmeter常用元件有哪些?jmeter如何管理cookie和session信息?jmeter中如何实现关联?jmeter中断言方式?jmeter参数化的方式有哪几种可以实现?Jmeter怎么录制,怎么过滤?JMeter结果树响应数据中文乱码如何解决?用户定义的变量和用户参数的区别?Jmeter怎么实现持续集成测试?在项目中如何用jmeter进行http接口测试?(重点)在Jmeter安装目录bin中,找到jmet

    2022年9月30日
    0
  • JDBC+Servlet+JSP整合开发之28-JSP_标准标签(JSTL)

    JDBC+Servlet+JSP整合开发之28-JSP_标准标签(JSTL)

    2021年8月6日
    50

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号