函数式接口的核心是理解“一个抽象方法如何支撑行为传递”,应从Runnable入手建立直觉,再掌握Supplier、Consumer、Function、Predicate四大接口的输入输出契约,优先使用JDK内置接口并善用andThen/compose实现逻辑组合。

函数式接口不是背概念,而是理解“一个抽象方法怎么撑起行为传递”这件事。学得快的关键,是顺着用法倒推设计逻辑,而不是先啃定义再写代码。
从 Runnable 入手,先建立直觉
不用一上来就记 Predicate 或 Function,直接看最熟悉的 Runnable:
- 它只有一个抽象方法
run(),无参数、无返回值 -
new Thread(() -> System.out.println("hello")).start();这行代码里,Lambda 就是Runnable的实现 - 说明:只要接口满足“只缺一个方法”,你就能用 Lambda 去填空
盯住四大核心接口的“输入-输出契约”
它们不是并列关系,而是按数据流向分工的:
- Supplier<T>:不收参数,只吐东西 → 适合创建对象、生成随机数、取当前时间
- Consumer<T>:收一个参数,不还结果 → 适合打印、存库、发消息
-
Function<T,R>:收一个,还一个(类型可变)→ 适合转换,比如
String::length、s -> s.trim() -
Predicate<T>:收一个,还
boolean→ 适合判断,比如s -> s.startsWith("A")
记住这四句话,比背方法签名管用得多。
立即学习“Java免费学习笔记(深入)”;
动手时优先用 JDK 内置,别急着自定义
90% 的场景,java.util.function 里的接口已经够用:
- 要过滤列表?用
Predicate+stream().filter() - 要转换每个元素?用
Function+stream().map() - 要遍历并做点事?用
Consumer+forEach() - 要生成一堆对象?用
Supplier+Stream.generate()
只有当你发现现有接口没法准确表达语义(比如“把字符串转成带校验的用户对象”),再考虑加 @FunctionalInterface 自定义。
用组合代替嵌套,体会函数式真正价值
别只停留在单个 Lambda,试试链式调用:
Function<String, Integer> strToInt = Integer::parseInt;Function<Integer, Boolean> isEven = i -> i % 2 == 0;Function<String, Boolean> isEvenStr = strToInt.andThen(isEven);System.out.println(isEvenStr.apply("4")); // true
这种 andThen、compose 的能力,才是函数式接口区别于普通接口的地方——它让逻辑可拼装、可复用、可测试。


















