java8 stream流操作的flatMap

我们来详细解释一下 Java 8 Stream API 中的 flatMap 操作。理解 flatMap 的关键在于将其与 map 操作进行对比。

​核心概念:​

  1. map 操作:​

    • 作用:将一个流中的每个元素​​转换​​为另一个元素(类型可以不同)。
    • 输入:一个元素 T
    • 输出:一个元素 R (通过你提供的 Function<T, R> 函数)
    • 结果流:一个包含所有转换后元素 R 的流 Stream<R>
    • ​特点:​​ 输入一个元素,输出一个元素。输入流中有 N 个元素,输出流中也有 N 个元素(类型可能变了)。
  2. flatMap 操作:​

    • 作用:将一个流中的每个元素​​转换​​为​​零个、一个或多个新元素组成的流​​,然后将所有这些生成的流​​“扁平化”​​ 连接成一个单一的流。
    • 输入:一个元素 T
    • 输出:一个流 Stream<R> (通过你提供的 Function<T, Stream<R>> 函数)
    • 结果流:将每个输入元素 T 产生的 Stream<R> 中的所有元素​​连接(展平)​​ 起来形成的最终 Stream<R>
    • ​特点:​
      • 输入一个元素,输出一个​​流​​(包含零个、一个或多个元素)。
      • 然后将所有输出的流“拍扁”,合并成一个单一的流。
      • 输入流中有 N 个元素,输出流中的元素个数可以是 0 到 M(M 是所有生成的流中元素的总和)。元素类型通常也会改变。

​为什么叫 “flatMap”?​

  • ​Map:​​ 因为它像 map 一样,对每个元素应用一个转换函数。
  • ​Flat:​​ 因为它将转换后产生的​​嵌套结构(流中的流)​​ “展平”(flatten)成一个单一的流。

​核心函数式接口:​

  • map 使用 Function<T, R>: R apply(T t)
  • flatMap 使用 Function<T, Stream<R>>: Stream<R> apply(T t) — ​​注意返回值必须是 Stream!​

​常见使用场景:​

  1. ​展平嵌套集合:​​ 这是最经典的用法。

    List<List<String>> nestedList = Arrays.asList(
        Arrays.asList("a", "b", "c"),
        Arrays.asList("d", "e"),
        Arrays.asList("f", "g", "h")
    );
    
    // 使用 map: 得到一个包含3个流的流 (Stream<Stream<String>>)
    Stream<Stream<String>> streamOfStreams = nestedList.stream().map(list -> list.stream());
    
    // 使用 flatMap: 得到一个包含所有字符串的单一流 (Stream<String>)
    Stream<String> flatStream = nestedList.stream().flatMap(list -> list.stream());
    
    List<String> flattenedList = flatStream.collect(Collectors.toList());
    // flattenedList 结果为: ["a", "b", "c", "d", "e", "f", "g", "h"]
  2. 处理可能产生多个结果的元素:​​ 例如,一个字符串数组,你想把每个字符串按空格分割成单词。
     
    List<String> lines = Arrays.asList("Hello world", "Java 8 Streams", "flatMap example");
    
    // 使用 map + split: 得到一个包含字符串数组的流 (Stream<String[]>)
    Stream<String[]> streamOfArrays = lines.stream().map(line -> line.split(" "));
    
    // 使用 flatMap + Arrays.stream(): 得到一个包含所有单词的单一流 (Stream<String>)
    Stream<String> wordsStream = lines.stream()
                                    .flatMap(line -> Arrays.stream(line.split(" ")));
    
    List<String> words = wordsStream.collect(Collectors.toList());
    // words 结果为: ["Hello", "world", "Java", "8", "Streams", "flatMap", "example"]

总结 flatMap:​

  • ​目的:​​ 处理那些一个输入元素会映射到​​多个输出元素​​(或者需要表示为流)的场景,并将这些输出​​平滑地合并​​到最终的结果流中。
  • ​关键:​​ 你提供给 flatMap 的函数 (Function<T, Stream<R>>) ​​必须返回一个 Stream 对象​​。
  • ​结果:​​ 将输入流中每个元素产生的所有 Stream<R> 的内容连接起来,形成一个单一的、连续的 Stream<R>
  • ​效果:​​ “展平”嵌套结构或一对多映射。

简单来说,当你遇到类似“我有一个列表,里面的每个元素本身又是一个列表(或其他集合),我想把它们合并成一个大列表”或者“我有一个流,每个元素处理后会得到一组结果,我想把这些结果都收集到一个流里”的情况时,flatMap 就是你的好帮手。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值