flatMap打平嵌套集合的核心是逐层解包:每次仅降一维,两层嵌套需一次flatMap,三层需两次链式调用,对象嵌套按属性路径逐级flatmap,且flatMap实现一对多映射并自动展平,而map仅一对一转换。

用 flatMap 打平嵌套集合,核心是“逐层解包”:每次 flatMap 只降一维,多级结构需链式调用,不能一步到位。
两层嵌套(List<List<T>> → List<T>)
这是最常见场景。关键在于把每个子列表转成 Stream<T>,再由 flatMap 合并:
- 必须用
list.stream(),不能直接返回list(类型不匹配) - 提前过滤
null子列表,避免NullPointerException - 示例:
nestedList.stream().filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList())
三层及以上嵌套(如 List<List<List<String>>>)
每深一层,就多一次 flatMap:
- 三级嵌套需两次
flatMap:先降到二级,再降到一级 - 代码体现为链式调用:
.flatMap(x -> x.stream()).flatMap(y -> y.stream()) - 超过三层时,建议回头检查数据建模——反复嵌套往往说明结构设计可优化,而非硬堆
flatMap
对象嵌套集合(如 School → Class → Student → Course)
当嵌套发生在对象属性中,flatMap 依然适用,只需按路径逐级提取:
- 每级调用对应一个
flatMap:比如schools.stream().flatMap(s -> s.getClasses().stream()) - 若某属性可能为
null,用Objects.nonNull过滤或Optional.ofNullable(...).stream()安全转换 - 最终可衔接去重、过滤等操作,例如
.map(Student::getCourseName).distinct()
flatMap 和 map 的关键区别
别混淆两者作用:
-
map是一对一:输入一个元素,输出一个元素(哪怕是个集合) -
flatMap是一对多 + 自动展平:输入一个元素,输出一个Stream,所有流被合并为单一流 - 错误写法:
stream().map(list -> list.stream())→ 得到的是Stream<Stream<T>>,不是扁平结果

















