亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述死磕Lambda表达式:Lambda的使用相关的知识,希望能为你提供帮助。
在哪使用Lambda表达式?
在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达式的例子,就是按照品牌给口罩列表进行排序:
maskList.sort((Mask o1, Mask o2) ->
o1.getBrand().compareTo(o2.getBrand()));
这里使用的
sort
方法的参数类型是Comparator&
lt;
T&
gt;
,我们就是把Lambda表达式作为Comparator&
lt;
T&
gt;
传入sort
方法中的。Comparator&
lt;
T&
gt;
就是一个函数式接口,那么什么是函数式接口?函数式接口
函数式接口就是有且仅有一个抽象方法的接口。上面提到的
Comparator&
lt;
T&
gt;
接口,虽然有很多默认方法,但有且仅有一个抽象方法compare
,所以它仍然是一个函数式接口。再举一个例子:package java.util.concurrent;
@FunctionalInterface
public interface Callable<
V>
V call() throws Exception;
Callable
接口只有一个call
抽象方法,所以它也是函数式接口。你可以已经发现了,
Callable
接口上有一个注解@FunctionalInterface
,该注解用于标志该接口是一个函数式接口。如果你编写了一个不是函数式接口的接口,并且加了@FunctionalInterface
注解,编译就会报错,需要注意一下。看了以上的例子,是不是撸胳膊挽袖子准备大干一场?别急,检验出真知,我们先简单测试一下。以下三个接口,哪些是函数式接口,哪些不是函数式接口?
- Runnable
package java.lang;
@FunctionalInterface
public interface Runnable
public abstract void run();
- Task
package com.sun.jmx.snmp.tasks;
public interface Task extends Runnable
public void cancel();
- Serializable
package java.io;
public interface Serializable
请思考片刻…
.
.
.
文章图片
.
.
.
宣布答案:
Runnable
只有一个抽象方法run
,所以是函数式接口Task
有两个抽象方法,分别是自己的cancel
方法和从Runnable
继承而来的run
方法,所以不是函数式接口。Serializable
没有任何一个方法,所以不是函数式接口。
实现函数式接口
了解了什么是函数式接口以后,我们就可以直接使用Lambda表达式为函数式接口提供实现了,并且还可以把整个Lambda表达式作为函数式接口的实例。比如上面提到的
Runnable
接口,我们就是这样直接赋值:Runnable runnable = () ->
System.out.println("万猫学社");
;
到目前为止,我们已经知道在哪使用Lambda表达式,那么该如何正确的使用Lambda表达式呢?
怎么使用Lambda表达式?
从上面
Runnable
接口实例的例子中,可以看出:Runnable
接口的run
方法没有入参没有返回,该方法的签名是() -&
gt;
void
;Lambda表达式同样的也没有入参没有返回,该表达式的签名是() -&
gt;
void
。也就是说:函数式接口的抽象方法的签名和Lambda表达式的签名必须一致。
再比如,按照品牌给口罩列表进行排序的例子,
Comparator&
lt;
T&
gt;
接口的compare
方法的签名是(T ,T) -&
gt;
int
,Lambda表达式的签名同样也是(T ,T) -&
gt;
int
。为了加深理解,我们再来做个小测试,看看哪些代码正确使用了Lambda表达式?
Callable
Callable< String> callable = () -> return "万猫学社"; ;
Runnable
Runnable runnable = () -> return "万猫学社"; ;
Comparator& lt; Mask& gt;
maskList.sort((Mask o1, Mask o2) -> if (o1.getBrand().equals(o2.getBrand())) return o1.getType().compareTo(o2.getType()); else return o1.getBrand().compareTo(o2.getBrand()); );
请思考片刻…
.
.
.
文章图片
.
.
.
宣布答案:
Callable
:正确,Lambda表达式的签名是() -& gt; String
,与Callable& lt; String& gt;
接口的唯一抽象方法call
的签名匹配,所以是正确的。Runnable
:错误,Lambda表达式的签名是() -& gt; String
,但是Runnable
接口的唯一抽象方法run
的签名是() -& gt; void
,两者不匹配,所以是错误的。Comparator& lt; Mask& gt;
:正确,Lambda表达式的签名是(Mask, Mask) -& gt; int
,与Comparator& lt; Mask& gt;
接口的唯一抽象方法compare
的签名匹配,所以是正确的。
总结
【死磕Lambda表达式(Lambda的使用)】有且仅有一个抽象方法的接口叫做函数式接口,Lambda表达式可以直接作为函数式接口的实例,函数式接口的抽象方法的签名和Lambda表达式的签名必须一致。
《死磕Lambda表达式》目录
- 死磕Lambda表达式(一):初识Lambda
- 死磕Lambda表达式(二):Lambda的使用
- 死磕Lambda表达式(三):更简洁的Lambda
- 死磕Lambda表达式(四):常用的函数式接口
- 死磕Lambda表达式(五):Comparator复合
- 死磕Lambda表达式(六):Consumer、Predicate、Function复合
推荐阅读
- JVS开源框架系列(JVS轻应用可以做什么(「含开源地址」))
- Netty之非阻塞处理
- 信息安全深透测试与工房操作系统弱点扫描
- 云计算-10-Docker网络使用
- CentOS vim编辑器
- 数仓建模—OneID
- Keepalived+LVS实战案例( 单主架构实现WEB负载均衡及可用)
- Tars | 第2篇 TarsJava SpingBoot启动与负载均衡源码初探 #yyds干货盘点#
- 盘点微软对Windows8 Beta关键技巧改进