flatMap 展平嵌套集合的核心是“每个元素映射为一个Stream,再自动合并”,需确保映射函数返回Stream类型,null需前置过滤,多层嵌套需多次flatMap,适用于List、数组、Optional等可转Stream的结构。

用 flatMap 展平嵌套集合,关键在于“每个元素转成一个流,再合并”。它不是直接拆开嵌套,而是靠映射函数返回 Stream,由 flatMap 自动把所有子流拼成一个单层流。
处理 List> 最常用写法
这是最典型的二维扁平场景。必须对每个子列表调用 .stream(),不能直接返回子列表本身:
- 正确:用
list -> list.stream(),返回Stream<T> - 错误:用
list -> list或list -> list.toArray(),类型不匹配,编译失败 - 子列表为
null会抛NullPointerException,建议前置过滤:.filter(Objects::nonNull)
示例:
List<String> flat = nested.stream().filter(Objects::nonNull)
.flatMap(sub -> sub.stream())
.collect(Collectors.toList());
处理对象中嵌套的集合字段
比如 Student 类有 List<Course> getCourses(),想提取所有课程:
立即学习“Java免费学习笔记(深入)”;
- 先流化外层对象:
students.stream() - 对每个学生,调用
getCourses().stream()得到Stream<Course> - flatMap 自动合并所有学生的课程流
- 后续可接
distinct()、map()等操作
示例(去重课程名):
Set<String> courseNames = students.stream().flatMap(s -> s.getCourses().stream())
.map(Course::getName)
.distinct()
.collect(Collectors.toSet());
多层嵌套需多次 flatMap
flatMap 每次只降一维,不能自动递归展开:
-
List<List<List<String>>>→ 需两次flatMap才能到Stream<List<String>>,三次才到Stream<String> - 对象层级如
School → Class → Student → Course,每级对应一次flatMap - 漏掉某一层,类型就会卡在
Stream<Stream<...>>,后续操作无法进行
三层链式示例:
List<Course> allCourses = schools.stream().flatMap(school -> school.getClasses().stream())
.flatMap(cls -> cls.getStudents().stream())
.flatMap(stu -> stu.getCourses().stream())
.collect(Collectors.toList());
其他常见嵌套结构也能用
flatMap 不限于 List,只要能转成 Stream 就行:
-
字符串拆字符:
Stream.of("ab", "cd").flatMap(s -> s.chars().mapToObj(c -> (char)c)) -
Optional 处理:跳过空值,只保留有值的项:
optionals.stream().flatMap(Optional::stream) -
Set 或数组:先转流,再 flatMap,如
Arrays.stream(arr).flatMap(s -> Arrays.stream(s.split(",")))
注意中间流不能为 null,否则运行时报错;空集合(如空 List)是安全的,会生成空流,不影响合并。


















