集合类流操作的核心是将数据处理逻辑与循环解耦,通过链式调用表达需求;它为集合提供干净、可读、可复用的处理流水线,而非替代集合本身。

集合类流操作的核心是把“数据处理逻辑”从“怎么循环”里解放出来,用链式调用表达“要什么”。它不是替代集合,而是为集合提供一条干净、可读、可复用的处理流水线。
从集合创建 Stream 是第一步
几乎所有业务场景都从已有集合出发:
-
List、Set 直接调
.stream()或.parallelStream(); -
Map 要先选视角:用
keySet().stream()处理键,values().stream()处理值,entrySet().stream()同时操作键值对; - 数组别直接用
stream(),基本类型如int[]得用Arrays.stream(arr)或IntStream.of(),否则会变成装箱对象流,影响性能。
中间操作搭管道,不执行只定义逻辑
这些操作返回新 Stream,可无限串联,但不会触发计算:
-
filter 筛条件,比如
users.stream().filter(u -> u.isActive()); -
map 改结构,比如
.map(User::getEmail)提取邮箱字符串; -
flatMap 拆嵌套,比如部门列表转员工列表:
depts.stream().flatMap(d -> d.getUsers().stream()); -
sorted 排序,自然序用
.sorted(),按字段用.sorted(Comparator.comparing(User::getAge)); -
distinct 去重,依赖对象的
equals()和hashCode(),注意它不保证顺序。
终端操作收尾,真正执行并消耗流
一个 Stream 只能有一个终端操作,执行后流就关闭了:
-
collect 最常用,转成集合:
.collect(Collectors.toList())、.collect(Collectors.groupingBy(User::getDept))分组、.collect(Collectors.toMap(User::getId, Function.identity()))构建映射; -
count 返回元素总数,返回
long; - anyMatch / allMatch 布尔判断,短路执行,效率高;
- forEach 执行副作用(如打印、发消息),但不生成结果,不适合做聚合;
-
reduce 聚合计算,比如求和:
.reduce(0, Integer::sum),或带初始值的复杂累加。
几个关键细节不能忽略
实际写错多因忽视底层机制:
- Stream 是一次性消费的——调过
collect()就不能再forEach(),否则抛IllegalStateException; - 中间操作是惰性的,没终端操作,前面所有
filter、map都不运行; - 并行流
parallelStream()不一定更快,小数据量或操作简单时,线程开销反而拖慢; - 若需多次使用同一数据,别反复创建流,先
collect成集合再操作更稳妥。


















