首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Stream 流中 flatMap 方法详解

Stream 流中 flatMap 方法详解

作者头像
伯灵
发布2026-01-21 09:47:29
发布2026-01-21 09:47:29
2530
举报

🎯 1. flatMap() 到底是啥?

flatMap()Stream 里的中间操作,它的作用可以分两步理解:

  • 第一步:对流里的每个元素,先**映射(转换)**成一个 Stream
  • 第二步:把多个子流拍平成一个大的扁平流。

简单记忆map() 是一对一,flatMap() 是一对多。

🛠️ 2. 基础用法拆解

来看个例子:

代码语言:javascript
复制
List<String> list = List.of("Hello World", "Java Stream");

List<String> result = list.stream()
    .map(s -> s.split(" "))   // 转成 String[] 流
    .flatMap(Arrays::stream)    // 拍平成单层流
    .collect(Collectors.toList());

System.out.println(result);
执行过程解析

步骤

操作

结果

🎯 map()

每个元素转成数组

[["Hello", "World"], ["Java", "Stream"]]

🔥 flatMap()

拍平成单层流

["Hello", "World", "Java", "Stream"]


🔍 3. map() vs flatMap() 的区别

我们用个更直观的对比例子:

代码语言:javascript
复制
List<String> list = List.of("a,b,c", "d,e,f");

// map()
List<String[]> mapResult = list.stream()
    .map(s -> s.split(","))  // 每个元素变成 String[]
    .collect(Collectors.toList());

System.out.println(mapResult);
// 输出: [[a, b, c], [d, e, f]]  (嵌套数组)

// flatMap()
List<String> flatMapResult = list.stream()
    .flatMap(s -> Arrays.stream(s.split(",")))
    .collect(Collectors.toList());

System.out.println(flatMapResult);
// 输出: [a, b, c, d, e, f] (扁平化的一层)

总结

功能

map()

flatMap()

结果

返回嵌套结构(Stream<Stream>、List<List>等)

返回单层扁平结构

常见用途

单层对象转换

嵌套结构拍平、集合嵌套处理

结果类型

Stream<T[]> / Stream<List>

Stream<T>

示例转换

"A B" → ["A", "B"]

[["A", "B"], ["C", "D"]] → ["A", "B", "C", "D"]


🔥 4. 高阶实战场景

🎯 4.1. 嵌套集合扁平化
代码语言:javascript
复制
List<List<Integer>> numbers = List.of(
    List.of(1, 2, 3),
    List.of(4, 5, 6),
    List.of(7, 8, 9)
);

List<Integer> flatList = numbers.stream()
    .flatMap(List::stream)
    .collect(Collectors.toList());

System.out.println(flatList);
// 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]

🚀 4.2. 字符串拆分

假设我们有一组句子,想拆成单词:

代码语言:javascript
复制
List<String> sentences = List.of("Java is cool", "Stream API is powerful");

List<String> words = sentences.stream()
    .flatMap(s -> Arrays.stream(s.split(" ")))
    .collect(Collectors.toList());

System.out.println(words);
// 输出: [Java, is, cool, Stream, API, is, powerful]

🔥 4.3. 模拟 SQL JOIN

我们模拟多表连接(类似 SQL 的笛卡尔积):

代码语言:javascript
复制
List<String> names = List.of("Tom", "Jerry", "Mike");
List<String> hobbies = List.of("Coding", "Gaming", "Reading");

List<String> results = names.stream()
    .flatMap(name -> hobbies.stream().map(hobby -> name + " loves " + hobby))
    .collect(Collectors.toList());

results.forEach(System.out::println);

输出

代码语言:javascript
复制
Tom loves Coding
Tom loves Gaming
Tom loves Reading
Jerry loves Coding
Jerry loves Gaming
Jerry loves Reading
Mike loves Coding
Mike loves Gaming
Mike loves Reading

🔥 5. Optional 配合 flatMap()

Optional 也有 flatMap()!特别适合处理嵌套 Optional:

代码语言:javascript
复制
Optional<String> optionalName = Optional.of("Java");

Optional<String> upperName = optionalName
    .flatMap(name -> Optional.of(name.toUpperCase()));

System.out.println(upperName.orElse("No Name"));
// 输出: JAVA

如果用 map()

代码语言:javascript
复制
Optional<Optional<String>> nestedOptional = optionalName.map(name -> Optional.of(name.toUpperCase()));
System.out.println(nestedOptional);
// 输出: Optional[Optional[JAVA]]  (嵌套了两层)

🎉 6. 常见坑 & 注意事项

1️⃣ 避免空指针

如果 flatMap() 操作的是嵌套集合,务必确保子集合不为 null

代码语言:javascript
复制
List<List<String>> data = List.of(
    List.of("Java", "Python"),
    null // ❗️注意这里有null
);

List<String> result = data.stream()
    .filter(Objects::nonNull) // 先过滤掉null
    .flatMap(list -> list == null ? Stream.empty() : list.stream())
    .collect(Collectors.toList());

System.out.println(result);

2️⃣ 性能考虑

flatMap() 频繁拍平大数据集合时性能可能受影响,考虑分批次处理,或者用 parallelStream()


3️⃣ 嵌套层级太多

如果嵌套层次太多(List<List<List<T>>>),可以链式多次 flatMap()

代码语言:javascript
复制
List<List<List<String>>> deepNestedList = List.of(
    List.of(List.of("A", "B"), List.of("C")),
    List.of(List.of("D", "E"))
);

List<String> flatResult = deepNestedList.stream()
    .flatMap(List::stream)
    .flatMap(List::stream)
    .collect(Collectors.toList());

System.out.println(flatResult);
// 输出: [A, B, C, D, E]

🎁 7. 终极总结

特点

map()

flatMap()

转换关系

一对一转换

一对多(Stream 扁平化)

结果类型

Stream<Stream<T>>

Stream<T>

常用场景

数据转换,简单映射

嵌套集合、字符串拆解

Optional 嵌套处理

返回嵌套 Optional

解开嵌套 Optional

🌟 总结

通过本文的学习,我们深入了解了 flatMap() 在 Java Stream 中的强大功能。它不仅能够处理多层嵌套数据、拆分字符串、模拟 SQL JOIN,更能让你的代码更加简洁优雅,避免冗余的嵌套结构。

无论你是数据处理,还是解决复杂的集合操作,掌握 flatMap() 都将是你提升编码能力的关键一步。希望通过本文,大家能够更高效地利用这个工具,优化自己的代码结构,让代码不仅“能用”,更要“好用”。

如果你在学习过程中有任何疑问,或者有更多 flatMap() 的应用场景,欢迎在评论区留言,我们一起讨论!别忘了点赞收藏分享给更多需要的朋友哦!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🎯 1. flatMap() 到底是啥?
  • 🛠️ 2. 基础用法拆解
    • ✅ 执行过程解析
  • 🔍 3. map() vs flatMap() 的区别
  • 🔥 4. 高阶实战场景
    • 🎯 4.1. 嵌套集合扁平化
    • 🚀 4.2. 字符串拆分
    • 🔥 4.3. 模拟 SQL JOIN
  • 🔥 5. Optional 配合 flatMap()
  • 🎉 6. 常见坑 & 注意事项
  • 🎁 7. 终极总结
    • 🌟 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档