Java Stream.flatMap()方法详解

后端 潘老师 6个月前 (10-29) 189 ℃ (0) 扫码查看

Java 8的Stream.flatMap()方法用于将包含集合对象的Stream平铺为单个对象的Stream。在平铺操作过程中,原始Stream中所有集合中的对象被组合成一个单独的集合。

Stream<Collection> —-> flatMap() —-> Stream

// 快速指引
List<List<Integer>> listOfLists = Arrays.asList(
  Arrays.asList(1, 2, 3),
  Arrays.asList(4, 5),
  Arrays.asList(6, 7, 8)
);
List<Integer> flattenedList = listOfLists.stream()
  .flatMap(list -> list.stream())  // Flattening step
  .toList();
//打印 [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println("Flattened list: " + flattenedList);

1.什么是平铺?

想象一下,我们有一堆盒子,每个盒子里面有一些物品。现在,我们想把所有这些物品从盒子里拿出来,放进一个单独的盒子里。这就是flatMap()方法在流中所做的。它从流A中的不同集合中取出对象,并将所有对象放入新的流B中。

用通俗的话来说,平铺就是将多个集合/数组合并成一个。考虑以下示例。

在这个例子中,我们有一个包含3个数组的数组。经过平铺效应后,我们将得到一个结果数组,其中包含3个数组中的所有项目。

Before flattening     : [[1, 2, 3], [4, 5], [6, 7, 8]]

After flattening     : [1, 2, 3, 4, 5, 6, 7, 8]

在以下示例中,lines是一个文件中的行流。每一行由多个单词组成。words流是所有流平铺后的版本,变成一个由所有行中的所有单词组成的单个流。

Path path = ...;  //File Path

Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);

Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));

2.Stream flatMap() 方法

2.1 方法语法

Stream.flatMap()方法有以下语法:

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
  • R表示新流的元素类型。
  • mapper是一个无干扰的、无状态函数,应用于每个元素,产生一个新值的流。
  • 该方法返回一个类型为R的新流。

2.2. 方法特征

  • flatMap()是一种中间操作,并返回一个新的Stream。
  • 它返回一个Stream,其内容是将给定流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的结果。
  • flatMap()中用于转换的mapper函数是无状态的,只返回一个新值的流。
  • 每个映射的Stream在将其内容放入新Stream后关闭。
  • flatMap()操作将流平铺;与不进行平铺的map()操作相反。

3.Stream flatMap() 示例

示例1:将嵌套列表转换为单个列表

Java 8中使用了Stream.flatMap()函数的示例,用于获取包含来自列表的列表的所有元素的单个List。这个程序使用flatMap()操作将List<List>转换为List。

List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
List<Integer> list3 = Arrays.asList(7,8,9);
  
List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
 
List<Integer> listOfAllIntegers = listOfLists.stream()
          .flatMap(x -> x.stream())
          .collect(Collectors.toList());

System.out.println(listOfAllIntegers);

程序输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

示例2:将嵌套数组收集到单个列表中

Java 8中使用了Stream.flatMap()函数的示例,用于获取包含来自数组的数组的所有元素的单个List。

String[][] dataArray = new String[][]{{"a", "b"}, 
        {"c", "d"}, {"e", "f"}, {"g", "h"}};
         
List<String> listOfAllChars = Arrays.stream(dataArray)
              .flatMap(x -> Arrays.stream(x))
              .collect(Collectors.toList());

System.out.println(listOfAllChars);

程序输出:

[a, b, c, d, e, f, g, h]

4.使用IntStream,LongStream和DoubleStream进行平铺

Stream接口还有另外三个类似的方法,分别产生IntStream,LongStream和DoubleStream,如果平铺的流只包含数字值(如长整型,整数或双精度浮点数),则它们非常有用。

IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper)
LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper)
DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)

这些类提供了方便的方法来对Stream的所有元素执行数学运算,这通常是必需的。考虑以下示例。我们有一个数字列表的列表,我们想要所有数字的总和。

List<List<Integer>> listOfLists = Arrays.asList(
  Arrays.asList(1, 2, 3),
  Arrays.asList(4, 5),
  Arrays.asList(6, 7, 8)
);

int sum = listOfLists.stream()
  .flatMap(list -> list.stream()) // 平铺lists
  .mapToInt(Integer::intValue) // 转为 IntStream
  .sum(); // 计算总和

System.out.println("Sum of all numbers: " + sum);  //36

版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10470.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】