stream流中flatmap和map区别
Java Stream 流中一个非常经典、容易混淆的知识点,理解它对你以后函数式编程和链式处理非常有帮助。
✅ 核心区别:
方法 | 返回结果类型 | 作用 |
---|---|---|
map | 一对一映射(元素 → 元素) | 把流中的每个元素映射成另外一个对象,结果还是一个元素流 |
flatMap | 一对多扁平化映射(元素 → 流 → 合并成一个流) | 把流中的每个元素映射成一个流(或集合),然后把所有小流拍平成一个大流 |
✅ 举例理解
1️⃣ map
示例
List<String> words = List.of("hello", "world");
List<Integer> lengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(lengths); // [5, 5]
- 每个元素(String) → 映射成一个长度(Integer),所以是一对一。
2️⃣ flatMap
示例
List<String> words = List.of("hello", "world");
List<String> letters = words.stream()
.flatMap(word -> Arrays.stream(word.split("")))
.collect(Collectors.toList());
System.out.println(letters);
// [h, e, l, l, o, w, o, r, l, d]
- 每个元素(单词)→ 映射成一个「字符数组流」,然后把所有字符流合并,形成一个大流。
- 如果你用
map
而不是flatMap
,结果会是Stream<Stream<String>>
,嵌套两层,不方便处理。
✅ 图示理解(你可以在脑子里画一下)
map
:
[hello] -> [hello length = 5]
[world] -> [world length = 5]
结果: [5, 5]
flatMap
:
[hello] -> [h, e, l, l, o]
[world] -> [w, o, r, l, d]
结果: [h, e, l, l, o, w, o, r, l, d]
用一句话+小例子帮助记忆:
✅ 一句话记忆
- map:一个元素变成一个元素。
- flatMap:一个元素变成多个元素(拍平)。
✅ 简单例子
List<String> list = List.of("a,b", "c,d");
// 用 map:得到的还是两个字符串(中间逗号没拆)
list.stream()
.map(s -> s.split(","))
// 变成 Stream<String[]>,结果是嵌套数组
.forEach(arr -> System.out.println(Arrays.toString(arr)));
// 输出: [a, b] [c, d]
// 用 flatMap:每个元素拆成多个元素,拍平
list.stream()
.flatMap(s -> Arrays.stream(s.split(",")))
.forEach(System.out::println);
// 输出:a b c d
✅ 口诀
map
是「变形」flatMap
是「拆开」
✅ 前瞻性角度
- 如果将来处理复杂对象集合,
flatMap
是处理「嵌套集合」和「拆平」的利器。 - 比如
List<List<Integer>>
想要变成List<Integer>
,一行flatMap
解决。 - 在 WebFlux、Reactor 等响应式框架中,
flatMap
的思维同样重要(流中的流解构)。