Lambda表达式必须赋值给函数式接口,即有且仅一个抽象方法的接口;常用内置接口为Predicate、Consumer、Function、Supplier;语法可省略参数括号、return和大括号;典型场景包括集合操作、线程启动与排序;易错点有局部变量需事实final、不可抛受检异常、避免复杂逻辑。

复习 Java Lambda 表达式,关键不是背语法,而是理清“它为什么存在、在什么前提下能用、怎么写才自然、哪些地方容易踩坑”。下面按实战逻辑分四块梳理,直击重点。
一、必须先搞懂:函数式接口是 Lambda 的唯一入口
Lambda 不是独立函数,它只能赋值给有且仅有一个抽象方法的接口(即函数式接口)。这是硬性前提,不是可选项。
- @FunctionalInterface 注解不是必需的,但强烈建议加上——编译器会帮你检查是否意外加了第二个抽象方法
- 接口里可以有任意个 default 方法、static 方法,不影响其函数式接口身份
- Java 8 内置四大核心函数式接口要熟记用途:
• Predicate<T>:判断逻辑,test(T) 返回 boolean(如 x -> x > 10)
• Consumer<T>:消费数据,accept(T) 无返回(如 s -> System.out.println(s))
• Function<T, R>:转换数据,apply(T) 返回 R(如 s -> s.length())
• Supplier<T>:提供数据,get() 返回 T(如 () -> new ArrayList<>())
二、语法简化规则要练到条件反射
写 Lambda 不是炫技,而是让代码更干净。掌握三类常见省略场景即可覆盖 95% 的使用:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 参数部分:单参数时括号可省(s -> s.trim()),无参数必须写空括号(() -> "done"),多参数不能省((a, b) -> a + b)
- 箭头后单行表达式:自动推断返回值,省略大括号和 return((x, y) -> x * y 等价于 (x, y) -> { return x * y; })
- 箭头后多语句:必须加 {} 和 return((n) -> { System.out.println(n); return n * 2; })
三、典型应用场景要对应着记
Lambda 不是为写而写,它解决的是真实编码痛点。每个常用场景背后都对应一个函数式接口:
立即学习“Java免费学习笔记(深入)”;
- 集合遍历:用 Consumer,替代 for-each(list.forEach(s -> System.out.println(s)))
- 集合筛选:用 Predicate,配合 Stream.filter(list.stream().filter(s -> s.startsWith("A")))
- 集合转换:用 Function,配合 Stream.map(list.stream().map(String::toUpperCase))
- 线程启动:用 Runnable(new Thread(() -> doWork()).start())
- 排序定制:用 Comparator(list.sort((a, b) -> a.length() - b.length()))
四、易错点和限制必须避开
看似简单,但几个细节不注意就会编译失败或运行异常:
- Lambda 体内不能修改外部局部变量,除非该变量是 final 或“事实 final”(定义后没再赋值)
- 不能在 Lambda 中抛出受检异常(Exception),除非函数式接口的方法声明了 throws(比如自定义接口)
- 不要把复杂逻辑塞进 Lambda:超过 2–3 行就该抽成普通方法,再用方法引用(list.forEach(this::processItem))
- 慎用并行流(parallelStream)+ Lambda:非线程安全的操作(如往 ArrayList 添加元素)会导致数据错乱

















