这篇文章重点不在于如何去学习Lambda表达式,因为已经有很多那样的文章了。我想要描述的,是如何更迅速的去阅读和运用Lambda表达式。
1. 必须知道的知识
首先你要知道:
Lambda表达式都是通过接口来传递的。
换言之,看到Lambda表达式,你第一反应应该是,这个方法的参数一定是一个接口!
再者:
Lambda表达式对应的接口,只有一个接口方法。
举个例子:
Comparator.comparing(integer -> integer)
抛开Lambda表达式本身,此时你需要知道,Comparator.comparing方法需要传入一个接口,而接口只有一个方法。
2. 开始阅读
假设你不知道Comparator.comparing里面是啥接口,也不知道他的入参和返回值是什么。
还是上面的例子:
Comparator.comparing(integer -> integer+1)
请记住这样的规律:
对于 integer -> integer,我们拆分为三个部分:
第一部分: integer
第二部分: ->
第三部分: integer+1
其中,
第一部分
是入参,是一个变量;
第二部分
-> 表示 comparing方法中的接口;
第三部分
是接口中唯一的那个方法的方法体,有两种可能:
返回值(此时return可以忽略不写);
是一个表达式(表达式可能会返回一个值,也可能没有返回值);
在这个例子中,第三部分是 integer+1 ,此时我们无法判断 integer+1 是用作返回值,还是在执行一个变量+1的表达式。没关系,理解到这一部分,已经足够了。如果需要知道,就需要查看文档,或者通过IDE看一下有没有返回值了。
总结一下这个过程,可以这样表示:
x -> doSomething
一个参数 经过某个接口 接口的方法做的操作(接口中的方法的方法体)
类似的:
(x,y) -> {doSomething}
2个参数x,y 经过了某个接口 接口的方法做的操作(接口中的方法的方法体)
这个过程,我参考了《Java 8函数式编程》。书本里的描述写的可能比我更好。
3. 常用的函数接口及其规律
接触Lambda表达式的时候,看着一堆的箭头经常会觉得晕。
不知道为什么这个方法要传Function?
为什么那个又要传一个Consumer?
为什么这个接口有一个入参,那个接口有两个入参?
其实这主要还是自己不熟悉常用的函数接口造成的。
为了便于日常的使用,有必要记住常见的接口函数以及了解他们的一般规律。
常见函数接口及其作用
| 分类 | 参数/返回值 | 接口方法 | 作用 |
| :——– | :————– | :————– | :————————————— |
| Function | 有入有出 | apply或者以apply开头 | 用入参,经过操作,获取xxx |
| Consumer | 只入 | accept | 消费者,消费入参 |
| Predicate | 有入有出(只boolean出) | test | 断言,判断,根据入参来判断true/false |
| Operator | 有入有出 | apply或者以apply开头 | 1. Function的特例,部分接口继承自Function(部分是自定义的),所以也表示“从…经过操作,获取…”;
2.入参和返回值类型一致。 |
| Supplier | 只出 | get或者以get开头 | 供应者,工厂,提供xxx |
常用的函数接口分类
| 特征 | Second Header | 例子 |
| ——- | :————————– | :————— |
| Bi开头 | 表明该接口有两个入参 | BidFunction |
| 以基本类型开头 | 要么是返回这种基本类型,要么是只接收这种基本类型的入参 | DoublePredicate |
| 以To开头 | 表示返回值是这种类型 | ToDoubleFunction |
下面来尝试一下:
comparingDouble(ToDoubleFunction<? super T> keyExtractor)
对于上面的代码,来猜测一下ToDoubleFunction接口的入参和返回值。
因为是以ToDouble开头,所以返回值是double;
因为只有一个泛型,所以入参只有一个;
反过来,如果你是comparingDouble()方法的设计者。
此时你知道你需要入参,同时需要返回一个Double值,观察上面的表格,你会发现,也只能用Function或者Operator了。
如果你又觉得,你的入参和出参的类型是不一致的,那么肯定要排除掉Operator了,所以你只能从众多的Function中挑选一个。
所以,我觉得提早知道入参的个数和返回值类型,熟悉什么时候需要什么接口函数,这有助于我们对方法本身的理解,也能提高我们编写代码的效率。