flatmap用于将嵌套流扁平化,其核心是“一对多+合并”,如list经flatmap(list::stream)变为stream,之后可正常filter、map、collect;需避免在flatmap中修改原集合。

嵌套集合的本质是“流中含流”
嵌套集合,比如 List>
,从 Stream 角度看,并不是一个扁平的数据容器,而是一个“每项本身就是一个流”的结构。调用 .stream() 得到的是外层列表的流 —— 元素类型是 List<string></string>,不是 String。直接 map 或 filter 作用在子列表上,无法触达最内层元素。
flatMap 是专为“拆一层”设计的操作
flatMap 的核心逻辑是:对每个元素应用一个函数,该函数必须返回 Stream<t></t>;然后自动把所有生成的流拼接(concatenate)成一个新流。它完成的是“一对多 + 合并”两步动作,不可拆分。
-
map(List::stream)→ 得到Stream<stream>></stream>,仍是嵌套流,无法直接 collect -
flatMap(List::stream)→ 得到Stream<string></string>,真正扁平化,可继续 filter、map、collect
扁平化之后才能做聚合或转换
一旦通过 flatMap 展开,后续操作就和普通单层集合流完全一致:
- 去重汇总:
.flatMap(List::stream).distinct().collect(Collectors.toSet()) - 条件过滤后收集:
.flatMap(List::stream).filter(s -> s.length() > 3).collect(Collectors.toList()) - 跨层级映射(如结合外层对象):
.flatMap(list -> list.stream().map(s -> s.toUpperCase()))
注意引用语义与副作用陷阱
Stream 操作本身是无状态、不可变的 —— 它不会修改原始集合。但如果你在 flatMap 内部调用 subList.clear() 或 subList.add(...),这些操作会真实影响原数据,因为 List 引用未变。而像 list.set(i, new ArrayList()) 这类赋值,只改局部变量,不影响原始嵌套结构。
切记:不要在 flatMap 或 forEach 中试图“往外部集合 add 元素”,这违反流的设计原则,也容易出错。收集结果始终应通过 collect() 完成。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











