Java Stream中map与flatMap对比超详细教程

 更新时间:2025年05月13日 10:02:45   作者:不如打代码KK  
这篇文章主要介绍了Java Stream中map与flatMap对比的相关资料,map()用于一对一转换,而flatMap()用于一对多转换并合并结果,文章详细解释了每个方法的基本功能、典型应用场景和示例代码,需要的朋友可以参考下

一、核心区别对比

方法输入类型输出类型适用场景转换关系
map()Function<T,R>Stream<R>元素的一对一转换1:1
flatMap()Function<T,Stream<R>>Stream<R>元素的一对多转换并合并1:N

二、map()方法详解

1. 基本功能

将流中的每个元素转换为另一个对象

2. 典型应用场景

  • 类型转换
  • 提取对象属性
  • 数值计算

3. 示例代码

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapExample {
    public static void main(String[] args) {
        // 示例1:字符串转大写
        List<String> words = Arrays.asList("hello", "world");
        List<String> upperCaseWords = words.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println(upperCaseWords); // [HELLO, WORLD]

        // 示例2:提取对象属性
        class User {
            String name;
            User(String name) { this.name = name; }
            String getName() { return name; }
        }
        
        List<User> users = Arrays.asList(
            new User("Alice"),
            new User("Bob")
        );
        
        List<String> names = users.stream()
                .map(User::getName)
                .collect(Collectors.toList());
        System.out.println(names); // [Alice, Bob]
    }
}

三、flatMap()方法详解

1. 基本功能

将每个元素转换为流,然后将所有流合并为一个流

2. 典型应用场景

  • 处理嵌套集合
  • 拆分字符串为多个元素
  • 合并多个流

3. 示例代码

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FlatMapExample {
    public static void main(String[] args) {
        // 示例1:展开嵌套集合
        List<List<String>> nestedList = Arrays.asList(
            Arrays.asList("Java", "Python"),
            Arrays.asList("C++", "Go"),
            Arrays.asList("JavaScript", "TypeScript")
        );
        
        List<String> languages = nestedList.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
        System.out.println(languages); 
        // [Java, Python, C++, Go, JavaScript, TypeScript]

        // 示例2:拆分字符串为单词
        List<String> sentences = Arrays.asList(
            "Hello World",
            "Java Stream API"
        );
        
        List<String> words = sentences.stream()
                .flatMap(sentence -> Arrays.stream(sentence.split(" ")))
                .collect(Collectors.toList());
        System.out.println(words); 
        // [Hello, World, Java, Stream, API]
    }
}

四、对比使用案例

场景:学生选课数据处理

import java.util.*;
import java.util.stream.*;

class Student {
    String name;
    List<String> courses;
    
    Student(String name, List<String> courses) {
        this.name = name;
        this.courses = courses;
    }
    
    List<String> getCourses() { return courses; }
}

public class CompareExample {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student("Alice", Arrays.asList("Math", "Physics")),
            new Student("Bob", Arrays.asList("History", "Art"))
        );

        // 错误用法:map处理嵌套集合
        List<List<String>> wrongResult = students.stream()
                .map(Student::getCourses)
                .collect(Collectors.toList());
        System.out.println("错误结果:" + wrongResult); 
        // [[Math, Physics], [History, Art]]

        // 正确用法:flatMap展开嵌套集合
        List<String> correctResult = students.stream()
                .flatMap(student -> student.getCourses().stream())
                .collect(Collectors.toList());
        System.out.println("正确结果:" + correctResult); 
        // [Math, Physics, History, Art]

        // 综合应用:统计所有课程数量
        long courseCount = students.stream()
                .flatMap(student -> student.getCourses().stream())
                .count();
        System.out.println("总课程数:" + courseCount); // 4
    }
}

五、常见问题解答

Q1:什么时候该用flatMap?

当需要处理以下结构时:

  • List<List<T>> → List<T>
  • Stream<Stream<R>> → Stream<R>
  • 需要拆分元素为多个子元素时

Q2:可以组合使用map和flatMap吗?

可以,常见组合方式:

list.stream()
    .map(...)    // 初步转换
    .flatMap(...) // 展开处理
    .collect(...)

Q3:如何处理多层嵌套?

使用多次flatMap:

List<List<List<String>>> deepNested = ...;
deepNested.stream()
    .flatMap(List::stream)  // 展开第一层
    .flatMap(List::stream)  // 展开第二层
    .collect(...);

六、总结对比

操作输入元素输出元素数量最终结果结构
map单个元素1个新元素保持原流结构
flatMap单个元素0-N个新元素合并为单一流结构

选择原则

  • 需要简单转换单个元素 → 使用map()
  • 需要展开嵌套结构/生成多个元素 → 使用flatMap()

以上代码均可直接复制到Java 8+环境中运行,建议在IDE中实际测试观察输出结果,以加深理解。

到此这篇关于Java Stream中map与flatMap对比的文章就介绍到这了,更多相关Java map与flatMap对比内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java代码规范之不合理命名与重复代码示例详解

    java代码规范之不合理命名与重复代码示例详解

    这篇文章主要为大家介绍了java代码规范之不合理命名与重复代码示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 关于Java8新特性Optional类的详细解读

    关于Java8新特性Optional类的详细解读

    Optional类是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在,原来用 null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常,需要的朋友可以参考下
    2023-05-05
  • springboot项目如何部署到服务器

    springboot项目如何部署到服务器

    这篇文章主要介绍了springboot项目如何部署到服务器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java服务假死之生产事故的排查与优化问题

    Java服务假死之生产事故的排查与优化问题

    在服务器上通过curl命令调用一个Java服务的查询接口,半天没有任何响应,怎么进行这一现象排查呢,下面小编给大家记一次生产事故的排查与优化——Java服务假死问题,感兴趣的朋友一起看看吧
    2022-07-07
  • springmvc处理模型数据Map过程解析

    springmvc处理模型数据Map过程解析

    这篇文章主要介绍了springmvc处理模型数据Map过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • java向es中写入数据报错org.elasticsearch.action.ActionReque问题

    java向es中写入数据报错org.elasticsearch.action.ActionReque问题

    这篇文章主要介绍了java向es中写入数据报错org.elasticsearch.action.ActionReque问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Spring Boot中的路径变量示例详解

    Spring Boot中的路径变量示例详解

    SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及正则约束,是构建RESTful API的核心工具,本文给大家介绍Spring Boot中的路径变量示例,感兴趣的朋友一起看看吧
    2025-07-07
  • Java中实现多线程的几种方式总结

    Java中实现多线程的几种方式总结

    文章介绍了三种创建线程的方式:继承Thread类、实现Runnable接口和实现Callable接口,并比较了它们之间的区别和优缺点
    2025-01-01
  • 有关ThreadLocal的面试题你真的懂了吗

    有关ThreadLocal的面试题你真的懂了吗

    这篇文章主要介绍了面试题ThreadLocal,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06
  • 深入Synchronized和java.util.concurrent.locks.Lock的区别详解

    深入Synchronized和java.util.concurrent.locks.Lock的区别详解

    本篇文章是对Synchronized和java.util.concurrent.locks.Lock的区别进行了详细的分析介绍,需要的朋友参考下
    2013-06-06

最新评论