flatmap用于嵌套集合扁平化,它将每个元素映射为stream并自动合并;与map的一对一转换不同,flatmap支持一对多映射且展平层级;使用时必须返回stream,如sub.stream(),不可直接返回list。

嵌套集合扁平化,核心就是把多层结构“压平”成单层。flatMap 正是为此而生——它不只做转换,还自动合并结果,一步到位。
flatMap 与 map 的关键区别
map 是一对一:每个输入元素生成一个输出元素,结构不变。比如对 List>
调用 map,结果是 List>
,只是内容变了,层级还在。
flatMap 是一对多+展平:每个输入元素可映射出零个、一个或多个元素,并直接合并进最终流。对同样嵌套列表调用 flatMap,结果就是 List
- 用 map 处理嵌套集合,容易得到“集合的集合”,后续还得 flatten 或循环遍历
- 用 flatMap,只要确保映射函数返回 Stream(如 list.stream()),就能自然展平
- Java 中写错常见于:flatMap 接收了 List 却没转成 Stream,编译直接报错
正确写法:必须返回 Stream
对 List>
扁平化,lambda 里不能直接返回子列表,必须调用 .stream():
- ✅ 正确:listOfLists.stream().flatMap(sub -> sub.stream())
- ❌ 错误:listOfLists.stream().flatMap(sub -> sub)(类型不匹配)
同理,处理用户-邮箱关系时,user.getEmails().stream() 是标准写法;若 getEmails() 可能返回 null,应先防护:Optional.ofNullable(user.getEmails()).orElse(List.of()).stream()。
应对多层嵌套
每层嵌套需一次 flatMap,顺序展开即可:
-
List
- >>
- >>
- 再一层 → Stream
- >
- 第三层 → Stream
代码上就是链式调用三次 .flatMap(x -> x.stream())。超过三层时,建议回头检查数据建模是否合理,而非硬堆 flatMap。
空集合与边界情况
flatMap 对空集合天然友好:遇到空 List 或空 Stream,映射函数不会执行,直接返回空结果,无 NullPointerException 风险。
- 源集合为空?→ 结果为空,函数不触发
- 某子集合为空?→ 该位置不贡献任何元素,不影响其余数据
- 但若子集合可能为 null,就必须提前判空,否则在调用 .stream() 时崩溃










