在Java中如何使用Stream的flatMap展开数据结构

来源:安卓APP网作者:灯下变量头衔:程序员
导读:本期聚焦于小伙伴创作的《在Java中如何使用Stream的flatMap展开数据结构》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《在Java中如何使用Stream的flatMap展开数据结构》有用,将其分享出去将是对创作者最好的鼓励。

在Java的Stream流式处理体系中,flatMap是一个用于将嵌套数据结构展开的核心方法,它可以把多个流合并成一个流,解决多层嵌套集合的处理难题。相比传统的多层for循环,使用flatMap可以让代码更简洁,逻辑更清晰。

在Java中如何使用Stream的flatMap展开数据结构

flatMap的核心作用

flatMap的底层逻辑是先对原流中的每个元素执行一个返回流的函数,再把所有得到的流拼接成一个新的流,也就是完成“映射+扁平化”两个操作。它的典型使用场景包括:

  • 展开嵌套的集合结构,比如<code>List<List<String>></code>转成<code>List<String></code>
  • 处理对象中包含集合属性的场景,提取所有对象的集合元素
  • 拆分字符串等场景,将单个元素转换成多个元素后合并

基础用法:展开嵌套列表

最常见的场景是处理嵌套的列表结构,比如有一个包含多个子列表的主列表,需要把所有子列表的元素合并到一个新列表中。

传统循环的实现方式如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FlatMapDemo {
    public static void main(String[] args) {
        // 嵌套列表结构
        List<List<String>> nestedList = Arrays.asList(
            Arrays.asList("a", "b", "c"),
            Arrays.asList("d", "e"),
            Arrays.asList("f", "g", "h")
        );
        
        // 传统循环展开
        List<String> resultByLoop = new ArrayList<>();
        for (List<String> subList : nestedList) {
            resultByLoop.addAll(subList);
        }
        System.out.println(resultByLoop);
    }
}

使用flatMap的实现方式如下:

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

public class FlatMapDemo {
    public static void main(String[] args) {
        List<List<String>> nestedList = Arrays.asList(
            Arrays.asList("a", "b", "c"),
            Arrays.asList("d", "e"),
            Arrays.asList("f", "g", "h")
        );
        
        // 使用flatMap展开
        List<String> resultByFlatMap = nestedList.stream()
            .flatMap(subList -> subList.stream())
            .collect(Collectors.toList());
        System.out.println(resultByFlatMap);
    }
}

两种方式最终输出的结果都是[a, b, c, d, e, f, g, h],但flatMap的实现只需要一行核心逻辑,没有显式的循环嵌套。

进阶用法:处理对象嵌套集合的场景

实际开发中更常见的是对象包含集合属性的场景,比如有一个用户类,每个用户有多个爱好,需要提取所有用户的爱好组成一个新的集合。

首先定义用户类:

import java.util.List;

class User {
    private String name;
    private List<String> hobbies;
    
    public User(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }
    
    public List<String> getHobbies() {
        return hobbies;
    }
}

使用flatMap提取所有爱好的实现如下:

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

public class FlatMapDemo {
    public static void main(String[] args) {
        List<User> userList = Arrays.asList(
            new User("张三", Arrays.asList("篮球", "足球")),
            new User("李四", Arrays.asList("跑步", "游泳", "骑行")),
            new User("王五", Arrays.asList("绘画"))
        );
        
        // 提取所有用户的爱好
        List<String> allHobbies = userList.stream()
            .flatMap(user -> user.getHobbies().stream())
            .collect(Collectors.toList());
        System.out.println(allHobbies);
    }
}

运行后输出的结果是[篮球, 足球, 跑步, 游泳, 骑行, 绘画],flatMap自动把每个用户的爱好集合展开,合并成了最终的流。

其他常见使用场景

拆分字符串并展开

如果需要把一个句子拆分成单词,再处理所有单词,也可以使用flatMap:

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

public class FlatMapDemo {
    public static void main(String[] args) {
        List<String> sentences = Arrays.asList("hello world", "java stream flatMap", "test demo");
        
        // 拆分句子为单词并展开
        List<String> allWords = sentences.stream()
            .flatMap(sentence -> Arrays.stream(sentence.split(" ")))
            .collect(Collectors.toList());
        System.out.println(allWords);
    }
}

输出结果为[hello, world, java, stream, flatMap, test, demo]。

过滤空值后展开

如果嵌套结构中可能存在空集合,可以结合filter先过滤空值,再展开:

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

public class FlatMapDemo {
    public static void main(String[] args) {
        List<List<String>> nestedListWithNull = Arrays.asList(
            Arrays.asList("a", "b"),
            null,
            Arrays.asList("c", "d"),
            Arrays.asList()
        );
        
        List<String> result = nestedListWithNull.stream()
            .filter(subList -> subList != null && !subList.isEmpty())
            .flatMap(subList -> subList.stream())
            .collect(Collectors.toList());
        System.out.println(result);
    }
}

输出结果为[a, b, c, d],避免了空指针异常和空集合的干扰。

flatMap与map的区别

很多开发者会混淆map和flatMap的用法,两者的核心区别如下:

方法作用返回值类型
map对每个元素进行转换,返回的是转换后的元素组成的流Stream<R>,R是转换后的元素类型
flatMap对每个元素进行转换,转换结果是一个流,再把这些流合并成一个流Stream<R>,R是流中元素的类型,最终流是扁平化的

简单来说,map是一对一转换,flatMap是一对多转换并合并。比如<code>List<List<String>></code>用map处理的话,得到的是<code>Stream<List<String>></code>,而用flatMap处理得到的是<code>Stream<String></code>。

使用注意事项

  • flatMap的函数参数必须返回一个流,否则会编译报错
  • 如果原流中有null元素,直接调用flatMap可能会抛出空指针异常,建议先过滤null
  • flatMap是中间操作,需要结合终止操作才会执行,比如collect、forEach等
  • 展开后的流是无序的,如果需要保持原有顺序,不需要额外处理,Stream的有序性在flatMap后默认会保留,除非使用了并行流且原流是无序的

JavaStreamflatMap数据结构展开流式处理修改时间:2026-07-05 15:30:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。