Stream流中的Map与flatMap的区别及说明

 更新时间:2025年09月19日 15:23:48   作者:night_gu  
Map转换单个元素为新值,保持流长度;flatMap将元素转换为流再合并,实现扁平化处理,两者区别在于返回类型(对象vs流)及是否改变元素数量,适用于不同数据结构转换场景

Map与flatMap的基本概念

Map用于将流中的每个元素通过指定函数转换为另一个元素,生成一个一对一映射的新流。

例如将字符串流转换为对应长度流:

List<String> words = Arrays.asList("a", "bb", "ccc");
List<Integer> lengths = words.stream()
                             .map(String::length)
                             .collect(Collectors.toList()); 
// 输出: [1, 2, 3]

flatMap用于将每个元素转换为流后合并所有流,形成一对多映射的扁平化结果。

例如拆分字符串中的单词:

List<String> lines = Arrays.asList("hello world", "java stream");
List<String> words = lines.stream()
                          .flatMap(line -> Arrays.stream(line.split(" ")))
                          .collect(Collectors.toList());
// 输出: ["hello", "world", "java", "stream"]

核心区别对比

  • 输入输出关系

Map保持原始流元素数量不变,flatMap可能改变元素数量(如拆分为多个子流后合并)

  • 返回值要求

Map的Function返回普通对象,flatMap的Function必须返回Stream对象

  • 数据结构处理

Map适合单一元素转换,flatMap适合处理嵌套集合(如List<List>)

典型应用场景

Map适用场景

数据类型转换(String→Integer)、属性提取(对象→ID)、简单计算(数值→平方值)

flatMap适用场景

  • 合并多个集合:List<List<Integer>> → List<Integer>
  • 分解复合结构:字符串句子→单词流、树节点→子树节点流
  • 过滤后展开操作:先filter再flatMap处理有效数据

性能注意事项

flatMap涉及流合并操作,可能产生更多临时对象。

对于简单转换优先使用map,多层嵌套数据结构才使用flatMap。

代码示例对比

处理书籍作者场景:

// 使用map(保留嵌套结构)
List<Book> books = ...;
List<List<String>> authors = books.stream()
                                 .map(Book::getAuthors)
                                 .collect(Collectors.toList());

// 使用flatMap(扁平化结构)
List<String> allAuthors = books.stream()
                              .flatMap(book -> book.getAuthors().stream())
                              .collect(Collectors.toList());

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java同步关键字synchronize底层实现原理解析

    Java同步关键字synchronize底层实现原理解析

    synchronized关键字对大家来说并不陌生,当我们遇到并发情况时,优先会想到用synchronized关键字去解决,synchronized确实能够帮助我们去解决并发的问题,接下来通过本文给大家分享java synchronize底层实现原理,感兴趣的朋友一起看看吧
    2021-08-08
  • Java中创建ZIP文件的方法

    Java中创建ZIP文件的方法

    本文通过一段简单代码给大家介绍了java中创建zip文件的方法,代码超简单,感兴趣的朋友跟随脚本之家小编一起看看吧
    2018-06-06
  • SpringBoot如何使用validator框架优雅地校验参数

    SpringBoot如何使用validator框架优雅地校验参数

    文章介绍了如何使用SpringValidation进行参数校验,包括引入依赖、@requestBody和@requestParam参数校验、统一异常处理、分组校验、嵌套校验、自定义校验、业务规则校验以及@Valid和@Validated的区别,同时,列举了常用的BeanValidation和HibernateValidator注解
    2025-02-02
  • JDK版本修改不生效的解决方法

    JDK版本修改不生效的解决方法

    本文主要介绍了在配置新电脑环境时遇到JDK版本切换失败的问题,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • Java 17 更新后的 strictfp 关键字

    Java 17 更新后的 strictfp 关键字

    strictfp 可能是最没有存在感的关键字了,很多人写了多年 Java 甚至都不知道它的存在,strictfp,字面意思就是严格的浮点型。这玩意儿居然还有个关键字,可见其地位还是很高的。下面文章小编就带大家详细介绍其关键字,需要的朋友可以参考一下
    2021-09-09
  • 详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析

    详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析

    这篇文章主要介绍了详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 基于HTTP协议实现简单RPC框架的方法详解

    基于HTTP协议实现简单RPC框架的方法详解

    RPC全名(Remote Procedure Call),翻译过来就是远程过程调用,本文将为大家介绍如何基于HTTP协议实现简单RPC框架,感兴趣的小伙伴可以了解一下
    2023-06-06
  • 长度最小的子数组题目详解(Java版)

    长度最小的子数组题目详解(Java版)

    这篇文章主要给大家介绍了关于长度最小的子数组(Java版)的相关资料,这到题来自力扣,通过学习本文对大家理解这道题目有很大的帮助,需要的朋友可以参考下
    2023-12-12
  • Java ArrayList扩容机制原理深入分析

    Java ArrayList扩容机制原理深入分析

    在Java中,ArrayList是最常用的集合之一。它是一种容器,它的内部定义了一个Object类型的数组elementData,因此可用于存储任意类型的数据。我们知道,数组是长度恒定的。而ArrayList相当于是一个长度可变的动态数组,一起来看看的它的扩容机制
    2023-02-02
  • java实现文件归档和还原

    java实现文件归档和还原

    这篇文章主要为大家详细介绍了java实现文件归档和还原,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09

最新评论