背景与动机
Lambda 和 Stream 让 Java 能用更声明式的方式处理集合数据。
传统写法关注“怎么循环”,Stream 写法更关注“要得到什么结果”。这对过滤、转换、聚合这类集合操作尤其有用。
核心原理拆解
1. Lambda 表达式
Lambda 的基本形式是:
(参数) -> 表达式或代码块例如:
names.forEach(name -> System.out.println(name));如果代码块较长,可以写成:
names.forEach(name -> { System.out.println(name);});2. 函数式接口
Lambda 不是凭空存在的,它需要匹配一个只有一个抽象方法的接口,这类接口叫函数式接口。
例如 Runnable:
Runnable task = () -> System.out.println("run");task.run();3. Stream 的常见操作

filter 用于过滤:
names.stream() .filter(name -> name.length() > 3);map 用于转换:
names.stream() .map(String::toUpperCase);collect 用于收集结果:
List<String> result = names.stream() .filter(name -> name.length() > 3) .toList();4. 中间操作和终止操作
Stream 操作分为:
- 中间操作:
filter、map,返回新的 Stream - 终止操作:
forEach、count、toList,触发实际计算
没有终止操作时,中间操作通常不会真正执行。
最小可运行代码示例
import java.util.List;
public class LambdaStreamDemo { public static void main(String[] args) { List<String> names = List.of("Tom", "Jerry", "Alice");
List<String> result = names.stream() .filter(name -> name.length() > 3) .map(String::toUpperCase) .toList();
result.forEach(System.out::println); }}输出:
JERRYALICE常见陷阱与错误示例
1. 忘记终止操作
names.stream() .filter(name -> { System.out.println(name); return name.length() > 3; });没有终止操作时,过滤逻辑不会被触发。
2. 在 Stream 中写复杂副作用
Stream 更适合表达数据转换。如果在 map、filter 里夹杂大量修改外部状态的逻辑,代码可读性会变差。
3. 为了用 Stream 而用 Stream
简单循环不一定需要改成 Stream。可读性比形式更重要。
面试高频问题
1. Lambda 表达式依赖什么
Lambda 需要匹配函数式接口,也就是只有一个抽象方法的接口。
2. Stream 的 filter 和 map 有什么区别
filter 用于筛选元素,元素类型通常不变;map 用于把元素转换成另一种值。
3. Stream 中间操作什么时候执行
通常在遇到终止操作时才会触发执行,例如 forEach、count、toList。
一句话总结
Lambda 用简洁方式表达行为,Stream 用声明式链式操作处理集合,但要注意终止操作和副作用边界。