函数式接口 Lambda 表达式好搭档:Predicate、Function、Consumer、Supplier
-
- [一、Lambda 表达式是什么?](#一、Lambda 表达式是什么?)
-
- [Lambda 的语法](#Lambda 的语法)
- [二、函数式接口 ------ Lambda 的好搭档](#二、函数式接口 —— Lambda 的好搭档)
- 三、四大核心函数式接口详解
-
- [1. Predicate<T> ------ 判断真假(过滤)](#1. Predicate<T> —— 判断真假(过滤))
- [2. Function<T,R> ------ 转换(映射)](#2. Function<T,R> —— 转换(映射))
- [3. Consumer<T> ------ 消费(处理)](#3. Consumer<T> —— 消费(处理))
- [4. Supplier<T> ------ 供应(生产)](#4. Supplier<T> —— 供应(生产))
- 四、它们之间的"化学反应"
- 五、总结
一、Lambda 表达式是什么?
Lambda 表达式可以理解为一段可以传递的代码块 ,它的本质是一个匿名函数 (没有名字的函数)。在 Java 8 之前,如果你想传递一段行为(比如点击按钮后的操作、集合遍历的逻辑),通常得写一个冗长的匿名内部类,代码看起来很臃肿。Lambda 的出现就是为了简化这种写法。
举个最简单的例子:创建一个线程。
java
// 旧写法:匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程运行中");
}
}).start();
// Lambda 写法
new Thread(() -> System.out.println("线程运行中")).start();
是不是瞬间清爽了很多?Lambda 让我们只关注"做什么",而不用写一堆样板代码。
Lambda 的语法
java
(参数列表) -> { 方法体 }
常见形式:
-
无参数 :
() -> System.out.println("Hello") -
一个参数 :可以省略括号
x -> x * 2(但建议保留,更清晰) -
多个参数 :
(x, y) -> x + y -
多条语句 :需要大括号和
returnjava(x, y) -> { int sum = x + y; System.out.println(sum); return sum; }
二、函数式接口 ------ Lambda 的好搭档
Lambda 不能单独使用,它必须赋值给一个函数式接口 。
什么是函数式接口?就是只有一个抽象方法 的接口(可以有默认方法或静态方法)。Java 中用 @FunctionalInterface 注解来标记(非必须,但推荐)。
常见的函数式接口有:Runnable、Comparator、ActionListener 等。Java 8 为了方便我们使用 Lambda,在 java.util.function 包下新增了几十个函数式接口,其中最常用的就是 Predicate、Function、Consumer、Supplier。下面我们逐一认识它们。
三、四大核心函数式接口详解
1. Predicate ------ 判断真假(过滤)
- 抽象方法 :
boolean test(T t) - 作用 :接收一个参数,返回一个
boolean值,常用于条件判断或过滤。
生活比喻 :就像一个安检员,检查一个人是否符合条件(比如年龄≥18),符合就放行(true),否则拒绝(false)。
代码示例:
java
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
// 判断字符串是否为空
Predicate<String> isEmpty = s -> s == null || s.length() == 0;
System.out.println(isEmpty.test("")); // true
System.out.println(isEmpty.test("hello")); // false
// 与 Stream 结合:过滤出长度 > 3 的字符串
List<String> list = Arrays.asList("Java", "Python", "C", "JavaScript");
list.stream()
.filter(s -> s.length() > 3) // filter 接受 Predicate
.forEach(System.out::println); // 输出: Java Python JavaScript
}
}
2. Function<T,R> ------ 转换(映射)
- 抽象方法 :
R apply(T t) - 作用 :接收一个
T类型的参数,返回一个R类型的结果,常用于类型转换或提取信息。
生活比喻:就像翻译官,把中文(T)翻译成英文(R)。
代码示例:
java
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
// 将字符串转换为它的长度
Function<String, Integer> strToLength = s -> s.length();
System.out.println(strToLength.apply("Java")); // 4
// 与 Stream 结合:将每个字符串转为大写
List<String> list = Arrays.asList("java", "python", "c++");
list.stream()
.map(s -> s.toUpperCase()) // map 接受 Function
.forEach(System.out::println); // JAVA PYTHON C++
}
}
3. Consumer ------ 消费(处理)
- 抽象方法 :
void accept(T t) - 作用 :接收一个参数,执行某些操作,没有返回值。常用于遍历集合、打印、存储等。
生活比喻:就像吃货,把食物(T)吃掉,但不产生新东西。
代码示例:
java
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
// 打印字符串
Consumer<String> print = s -> System.out.println(s);
print.accept("Hello Lambda"); // Hello Lambda
// 遍历集合并打印
List<String> list = Arrays.asList("A", "B", "C");
list.forEach(print); // forEach 接受 Consumer
}
}
4. Supplier ------ 供应(生产)
- 抽象方法 :
T get() - 作用 :不接受参数,返回一个
T类型的值。常用于工厂模式、延迟生成或提供默认值。
生活比喻:就像自动售货机,你不需要给它东西,它直接给你一瓶饮料(T)。
代码示例:
java
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
// 生成一个随机整数
Supplier<Integer> random = () -> (int)(Math.random() * 100);
System.out.println(random.get()); // 每次运行结果不同
// 创建新对象
Supplier<Student> studentFactory = () -> new Student("张三", 18);
Student stu = studentFactory.get(); // 调用 get 获得新对象
}
}
class Student {
String name;
int age;
// 构造方法...
}
四、它们之间的"化学反应"
这四个接口常常配合 Stream API 使用,产生强大的效果:
| 接口 | 常用 Stream 方法 | 作用 |
|---|---|---|
| Predicate | filter() |
过滤元素 |
| Function | map() |
转换元素 |
| Consumer | forEach() |
遍历处理 |
| Supplier | generate() |
生成无限流 |
例如,我们可以组合它们完成一个完整的操作:从一组数字中过滤出偶数,然后将每个偶数平方,最后打印结果。
java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream()
.filter(n -> n % 2 == 0) // Predicate
.map(n -> n * n) // Function
.forEach(System.out::println); // Consumer
// 输出:4 16 36
五、总结
| 接口 | 抽象方法 | 用途 | 常用场景 |
|---|---|---|---|
Predicate<T> |
boolean test(T) |
条件判断,返回布尔值 | 过滤、匹配 |
Function<T,R> |
R apply(T) |
转换,输入T输出R | 提取属性、类型转换 |
Consumer<T> |
void accept(T) |
消费,无返回值 | 遍历、打印、存储 |
Supplier<T> |
T get() |
生产,提供对象 | 工厂、懒加载、生成随机值 |