死磕Lambda表达式(二):Lambda的使用

简介: 函数式接口就是有且仅有一个抽象方法的接口。上面提到的`Comparator<T>`接口,虽然有很多默认方法,但有且仅有一个抽象方法`compare`,所以它仍然是一个函数式接口。
城市就是森林,每一个男人都是猎手,每一个女人都是陷阱。——《三体》

在哪使用Lambda表达式?

在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达式的例子,就是按照品牌给口罩列表进行排序:

maskList.sort((Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand()));

这里使用的sort方法的参数类型是Comparator<T>,我们就是把Lambda表达式作为Comparator<T>传入sort方法中的。Comparator<T>就是一个函数式接口,那么什么是函数式接口?

函数式接口

函数式接口就是有且仅有一个抽象方法的接口。上面提到的Comparator<T>接口,虽然有很多默认方法,但有且仅有一个抽象方法compare,所以它仍然是一个函数式接口。再举一个例子:

package java.util.concurrent;

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

Callable接口只有一个call抽象方法,所以它也是函数式接口。

你可以已经发现了,Callable接口上有一个注解@FunctionalInterface,该注解用于标志该接口是一个函数式接口。如果你编写了一个不是函数式接口的接口,并且加了@FunctionalInterface注解,编译就会报错,需要注意一下。

看了以上的例子,是不是撸胳膊挽袖子准备大干一场?别急,检验出真知,我们先简单测试一下。以下三个接口,哪些是函数式接口,哪些不是函数式接口?

  1. Runnable
package java.lang;

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
  1. Task
package com.sun.jmx.snmp.tasks;

public interface Task extends Runnable {
    public void cancel();
}
  1. Serializable
package java.io;

public interface Serializable {
}

请思考片刻…
.
.
.

.
.
.
宣布答案

  1. Runnable只有一个抽象方法run,所以是函数式接口
  2. Task有两个抽象方法,分别是自己的cancel方法和从Runnable继承而来的run方法,所以不是函数式接口。
  3. Serializable没有任何一个方法,所以不是函数式接口。

怎么样?都答对了嘛?

实现函数式接口

了解了什么是函数式接口以后,我们就可以直接使用Lambda表达式为函数式接口提供实现了,并且还可以把整个Lambda表达式作为函数式接口的实例。比如上面提到的Runnable接口,我们就是这样直接赋值:

Runnable runnable = () -> {
    System.out.println("万猫学社");
};

到目前为止,我们已经知道在哪使用Lambda表达式,那么该如何正确的使用Lambda表达式呢?

怎么使用Lambda表达式?

从上面Runnable接口实例的例子中,可以看出:Runnable接口的run方法没有入参没有返回,该方法的签名是() -> void;Lambda表达式同样的也没有入参没有返回,该表达式的签名是() -> void

也就是说:函数式接口的抽象方法的签名和Lambda表达式的签名必须一致。

再比如,按照品牌给口罩列表进行排序的例子,Comparator<T>接口的compare方法的签名是(T ,T) -> int,Lambda表达式的签名同样也是(T ,T) -> int

为了加深理解,我们再来做个小测试,看看哪些代码正确使用了Lambda表达式?

  1. Callable
Callable<String> callable = () -> {
    return "万猫学社";
};
  1. Runnable
Runnable runnable = () -> {
    return "万猫学社";
};
  1. Comparator<Mask>
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());
    }
});

请思考片刻…
.
.
.

.
.
.
宣布答案

  1. Callable:正确,Lambda表达式的签名是() -> String,与Callable<String>接口的唯一抽象方法call的签名匹配,所以是正确的。
  2. Runnable:错误,Lambda表达式的签名是() -> String,但是Runnable接口的唯一抽象方法run的签名是() -> void,两者不匹配,所以是错误的。
  3. Comparator<Mask>:正确,Lambda表达式的签名是(Mask, Mask) -> int,与Comparator<Mask>接口的唯一抽象方法compare的签名匹配,所以是正确的。

怎么样?都答对了嘛?

总结

有且仅有一个抽象方法的接口叫做函数式接口,Lambda表达式可以直接作为函数式接口的实例,函数式接口的抽象方法的签名和Lambda表达式的签名必须一致。

《死磕Lambda表达式》目录

文章持续更新,微信搜索「 万猫学社 」第一时间阅读。
相关文章
|
4天前
|
算法 程序员 编译器
C ++匿名函数:揭开C++ Lambda表达式的神秘面纱
C ++匿名函数:揭开C++ Lambda表达式的神秘面纱
65 0
|
4天前
|
设计模式 Java 程序员
为什么程序员喜欢用Lambda表达式?
“lambda 表达式”是一段可以传递的代码,因此它可以被执行一次或多次。在学习语法(甚至包括一些奇怪的术语)之前,我们先回顾一下之前在Java 中一直使用的相似的代码块。
26 0
|
10月前
|
SQL Java 数据库
Lambda表达式你到哪个境界了?
日常开发中,我们很多时候需要用到Java 8的Lambda表达式,它允许把函数作为一个方法的参数,让我们的代码更优雅、更简洁。所以整理了一波工作中,我常用的,有哪些Lambda表达式。看完一定会有帮助的。
|
12月前
|
自然语言处理 Java 编译器
都2023年了,如果不会Lambda表达式、函数式编程?你确定能看懂公司代码?
都2023年了,如果你不会Lambda表达式、函数式编程?你确定能看懂公司代码? 那么建议来了解一下Lambda表达式, 因为它使用简单,易操作,易上手而代码简洁,开发快速,一看就令人很爽😎😎😎 . 其实Lambda表达式接近自然语言,易于理解 , 集万千优点与一身, 比匿名内部类更加完美👉👉👉.下面来简单认识一下今天的主角Lambda表达式吧
87 0
|
Java 编译器
「 Java基础-Lambda 」试试Lambda表达式?通俗易懂得嘞!
本文从Lambda表达式的基础概念、函数式接口、以及Lambda表达式的常用示例几方面完整的讨论了这一Java8新增的特性,实际开发中确实为我们提供了许多便利,简化了代码。欢迎小伙伴继续提出不同的见解一起讨论!
「 Java基础-Lambda 」试试Lambda表达式?通俗易懂得嘞!
使用 Lambda 表达式的正确姿势,写得太好了叭
Lambda 表达式非常方便,在项目中一般在 stream 编程中用得比较多。 List<Student> studentList = gen(); Map<String, Student> map = studentList .stream() .collect(Collectors.toMap(Student::getId, a -> a, (a, b) -> a)); 理解一个 Lambda 表达式就三步: 1. 确认 Lambda 表达式的类型 2. 找到要实现的方法 3. 实现这个方法 就这三步,没其他的了。而每一步,都非常非常简单,以至于我分别展开讲一下,你就懂了。
|
并行计算 Java 编译器
还看不懂同事的代码?Lambda 表达式、函数接口了解一下
还看不懂同事的代码?Lambda 表达式、函数接口了解一下
202 0
|
Java
死磕Lambda表达式(一):初识Lambda
Lambda表达式是表示可传递匿名函数的一种简洁方式,Lambda表达式没有名称,但是有参数列表、函数主体、返回类型,还可能有一个可以抛出的异常列表。它是Java8新增的特性,有了它我
85 0
死磕Lambda表达式(一):初识Lambda
|
Java 编译器
死磕Lambda表达式(三):更简洁的Lambda
编译器可以通过函数式接口推断出Lambda表达式的参数类型,所以在编写Lambda表达式时,可以省略参数类型。比如:
113 0
死磕Lambda表达式(三):更简洁的Lambda
|
Java
死磕Lambda表达式(四):常用的函数式接口
在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要在 java.util.function 包中,下面简单介绍几个其中的接口及其使用示例。
128 0