flatMap()的核心作用是将“集合的集合”扁平化为单层集合,适用于List<List<T>>、List<Optional<T>>等嵌套结构,其本质是一对多映射后合并Stream,而map是一对一转换且保留层级。

flatMap() 的核心作用是把“集合的集合”变成“单层集合”,特别适合处理嵌套的 List<List<T>>、List<Optional<T>> 或 List<Stream<T>> 这类结构。
理解 flatMap 和 map 的关键区别
map 是一对一转换:每个元素变换成一个新元素(哪怕是个集合,结果还是 List<List<T>>);
flatMap 是一对多再“压平”:每个元素先映射成一个 Stream,然后所有 Stream 合并成一个 Stream。
简单记:map 保留层级,flatMap 拆掉一层括号。
常见用法一:扁平化 List<List<T>>
比如有学生列表,每个学生有多个课程,想得到所有课程的扁平列表:
- 先用
map(Student::getCourses)→ 得到Stream<List<Course>> - 再用
flatMap(list -> list.stream())→ 把每个List<Course>转成Stream<Course>并合并
合起来写就是:
立即学习“Java免费学习笔记(深入)”;
students.stream()
.flatMap(student -> student.getCourses().stream())
.collect(Collectors.toList());
常见用法二:处理 Optional 或可能为空的集合
当某个字段可能是 null 或 Optional.empty(),直接 map 会出错或保留空值;flatMap 可安全跳过:
-
Optional.ofNullable(user.getAddress()).map(Address::getCity)→ 返回Optional<String> -
Optional.ofNullable(user.getAddress()).flatMap(addr -> Optional.ofNullable(addr.getCity))→ 仍是Optional<String>,但链式更安全
在 Stream 中类似:用 flatMap(e -> e.getTags() != null ? e.getTags().stream() : Stream.empty()) 避免空指针。
常见用法三:拆分字符串或生成多个元素
比如把句子列表按空格切分成单词流:
-
sentences.stream().map(s -> s.split(" "))→ 得到Stream<String[]> -
sentences.stream().flatMap(s -> Arrays.stream(s.split(" ")))→ 直接得到Stream<String>
也可以用来“展开”一个元素为多个:比如数字 3 → 生成 [0,1,2],用 flatMap(n -> IntStream.range(0, n).boxed())。
不复杂但容易忽略:flatMap 接收的是 Function<T, Stream<R>>,返回必须是 Stream,不能直接返回 List 或数组 —— 得先转成 Stream。


















