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的新特性。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Hook(钩子技术)基本知识讲解,原理

    一、什么是HOOK(钩子)      对于Windows系统,它是建立在事件驱动机制上的,说白了就是整个系统都是通过消息传递实现的。hook(钩子)是一种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往目标窗口的消息并进行处理。所以说,我们可以在系统中自定义钩子,用来监视系统中特定事件的发生,完成特定功能,如屏幕取词,监视日志,截获键盘、鼠标输入等等。     钩子…

  • 【Linux】面试题(2021最新版)

    【Linux】面试题(2021最新版)Linux的体系结构Linux-查找特定文件Linux-对日志内容做统计Linux-批量替换文件内容

  • c语言中fprintf的作用,C语言中fprintf函数介绍

    c语言中fprintf的作用,C语言中fprintf函数介绍C语言中,如果简单的输出txt,或者dat文件,或者我们需要输出标准化格式化的的数据,那么我们就会需要这个函数,我在地球物理学专业课中实验课编程中,总会遇到这个函数,现在我就把收集来的信息分享一下。fprintf是C/C++中的一个格式化写—库函数,位于头文件中,其作用是格式化输出到一个流/文件中;函数原型为intfprintf(FILE*stream,constchar*forma…

    2022年10月18日
  • 搜索引擎的工作原理

    搜索引擎的工作原理搜索引擎的基本工作原理包括如下三个过程:首先在互联网中发现、搜集网页信息;同时对信息进行提取和组织建立索引库;再由检索器根据用户输入的查询关键字,在索引库中快速检出文档,进行文档与查询的相关度评价,对将要输出的结果进行排序,并将查询结果返回给用户。1、抓取网页。每个独立的搜索引擎都有自己的网页抓取程序爬虫(spider)。爬虫Spider顺着网页中的超链接,从这个网站爬到另一个网站,通过超链接…

  • MYSQL安装出现问题(The service already exists)

    MYSQL安装出现问题(The service already exists)1.Zip解压后管理员身份运行cmd(系统win10)2.输入命令cd/dF:\mysql-5.7.19-win32\bin(此为解压目录)3.输入安装命令mysqldinstall出现问题Theservicealreadyexists这是由于之前已经安装过mysql并且没有删除干净4.重新以管理员身份运行,输入scquerymysql,查看一下名为mysql的

  • 服务器seo优化,SEO诊断之网站服务器优化「建议收藏」

    服务器seo优化,SEO诊断之网站服务器优化「建议收藏」前一章节子凡已经通过网站域名检查做过最基础的SEO诊断,接下来也是网站SEO诊断中最基础,也是较为重要的要素,没有域名,没有服务器,网站就无处容身,也就不会存在子凡分享的SEO话题了。一、网站服务器速度的重要性在网站速度方面我们要求自己的网站速度当然是越快越好,如果网站打开速度在5~40毫秒是为最佳效果。假设你的网站打开速度基本都在100ms左右,对于个人博客或者网站算是比较给力…

发表回复

您的电子邮箱地址不会被公开。

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