flatMap() Method in Java 8

2025 年 5 月 7 日 | 阅读 10 分钟

在Java 8 Streams中,flatMap()方法将操作应用于映射函数,并提供元素值的流。这意味着在每个元素的每次迭代中,map()方法都会创建一个单独的新流。通过使用扁平化机制,它将所有流合并成一个单一的结果流。简而言之,它用于将“流的流”转换为“值的列表”。

flatMap() Method in Java 8

flatMap()方法的工作方式如下:

  • 扁平化(Flattening):它将多个集合或数组合并成一个单一的流。
  • 中间操作(Intermediate Operation):它返回一个新的流,并且可以与其他流操作链接。
  • 无状态函数(Stateless Function):flatMap()中使用的映射函数是无状态且非干涉的。

语法

该方法接受一个函数作为参数。它接受T作为参数,并返回R的流。

R: 这是一个类型参数,表示新流的元素类型。

mapper: 这是一个参数,是一个非干涉、无状态的函数,应用于每个元素。它产生一个新值流。

mapper具有以下属性:

非干涉(Non-Interfering):该属性表示mapper不会更改输入流中的元素。相反,它为输入流中的每个元素生成一个不同的结果。

无状态(Stateless):与依赖于先前处理过的项的状态化行为相反,无状态行为独立处理每个元素。因此,对于给定的输入,mapper在不考虑先前元素的情况下始终产生相同的输出。

总之,我们可以说flatMap()方法有助于将**Stream<Stream<T>>**转换为**Stream<T>**。它同时执行**扁平化(flat或flatten)**和**映射(map)**。Stream.flatMap()方法结合了这两种操作,即flat和map。

Java Stream.flatMap()方法的返回值

Java的**flatMap()**方法返回一个类型为**R**的新流。从语法中讨论的方法签名可以看出这一点。

该方法,**flatMap()**,暗示了两个不同的操作:

  1. 映射(Mapping):原始流的每个元素都映射到一个类型为**R**的元素流。
  2. 扁平化(Flattening):这些元素流然后被扁平化成一个单一的流。

让我们理解扁平化的含义。

什么是扁平化?

扁平化是指将嵌套的数据结构(例如集合的集合)转换为单一的、扁平的结构的过程。当我们在编程中想要简化嵌套数据(如列表或数组)到单一列表或数组时,通常会使用它。

在Java中,可以使用流来实现这一点,我们可以将列表的列表转换为单个列表。flatMap()方法通常在Java中用于执行扁平化。

例如,将整数列表的列表转换为单个整数列表,消除任何嵌套结构,从而得到一个一维集合。

扁平化示例

考虑以下列表的列表:

扁平化之前 [[1, 2, 3, 4], [7, 8, 9, 0], [5, 6], [12, 18, 19, 20, 17], [22]]

扁平化之后 [1, 2, 3, 4, 7, 8, 9, 0, 5, 6, 12, 18, 19, 20, 17, 22]

flatMap()方法示例

我们可以使用List::stream作为映射函数在流上调用flatMap()方法。执行流的终止操作时,flatMap()的每个元素都会提供一个单独的流。在最后阶段,flatMap()方法将所有流转换为一个新的流。在上面的流中,我们观察到它不包含重复值。

让我们创建一个Java程序并使用flatMap()方法。

示例

编译并运行

输出

List Before Applying mapping and Flattening:
[Printer, Mouse, Keyboard, Motherboard, Scanner, Projector, Lighten, Pen Drive, Charger, WIFI Adapter, Cooling Fan, CPU Cabinet, WebCam, USB Light, Microphone]
List After Applying Mapping and Flattening Operation:
[Printer, Mouse, Keyboard, Motherboard, Scanner, Projector, Light Pen, Pen Drive, Charger, WIFI Adapter, Cooling Fan, CPU Cabinet, WebCam, USB Light, Microphone]

Stream.flatMap()方法的使用场景

将嵌套列表扁平化为列表

将嵌套列表扁平化为单个列表是处理复杂数据结构时的常见操作。在Java 8中,可以使用flatMap()方法高效地实现这一点。

示例

编译并运行

输出

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

将嵌套数组扁平化为列表

将嵌套数组扁平化为单个列表是与扁平化嵌套列表类似的另一个常见操作。在Java 8中,也可以使用**flatMap()**方法高效地实现这一点,但处理数组的方式略有不同。

示例

编译并运行

输出

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

Java Stream.flatMap()与原始类型

在Java 8中,Stream API为原始类型提供了专门的流,例如**IntStream、LongStream**和**DoubleStream**。当使用这些原始流时,您可能需要使用**flatMap()**方法来扁平化原始类型的嵌套结构。

示例

编译并运行

输出

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

文本文件的单词计数

在文本处理和分析中,计算文本文件中的单词数量是一项基本任务。此操作在各种应用中非常有用,例如文本分析、内容管理和数据预处理。在Java中,我们可以使用Stream API高效地执行单词计数。Stream API提供了一种现代的、函数式的方法来处理元素序列,使其非常适合读取和操作文本文件等任务。

示例

编译并运行

输出

Word count: 37

Demo.txt

  1. 你好,**这是**一个示例文本文件。
  2. 它包含几个单词,分布在多行中。
  3. 我们正在使用**此**文件来测试单词计数程序。
  4. 每一行都将被读取和处理以计算单词数。

现在,我们已经理解了Stream类的两种方法,因为我们可以轻松地指出它们之间的关键区别。

Stream.flatMap()和Stream.map()方法之间的区别

下表描述了Stream.flatMap()和Stream.map()之间的关键区别。

flatMap() Method in Java 8
方面Stream.flatMap()Stream.map()
处理它处理流的流对象。它处理对象的流。
映射和扁平化它执行映射和扁平化。它仅执行映射。
转换它将数据从Stream<Stream<T>>转换为Stream<R>。它将数据从Stream<T>转换为Stream<R>。
映射它使用一对多映射。它使用一对一映射。
产出对于每个输入值,其mapper函数会产生多个值(值的流)。对于每个输入值,其mapper函数会产生单个值。
用法当mapper函数为每个输入值产生多个值时,使用flatMap()方法。当mapper函数为每个输入值产生单个值时,使用map()方法。
示例List<Integer> allDistinctNums = Stream.of(evens, odds, primes).flatMap(numList -> numList.stream()).distinct().collect(Collectors.toList());List<Integer> stringLengths = Stream.of("ab", "abcd", "abc").map(String::length).collect(Collectors.toList());

要记住的重要事项

  1. flatMap操作可以描述为带有扁平化的map。
  2. 它是一种惰性中间操作。
  3. 它将嵌套结构转换为扁平化的结构。
  4. 它克服了map()方法的一些限制。
  5. 它执行一对多映射。
  6. 它只需要一个称为mapper的参数,该参数本质上是非干涉和无状态的。

Java Stream.flatMap()方法MCQ

1. flatMap()方法执行以下哪种映射?

  1. 一对一
  2. 一对多
  3. 多对多
  4. 多对一

答案:2)

解释: 它执行一对多映射,涉及将一个值映射为零个或多个值。例如,当您将单个字符串流扁平化为零个或多个字符串值时,就会发生一对多映射。


2. flatMap()方法执行哪些操作?

  1. 映射
  2. 扁平化
  3. 映射和扁平化
  4. 以上都不是

答案:3)

解释: 它同时执行扁平化(flat或flatten)和映射(map)。Stream.flatMap()方法结合了这两种操作,即flat和map。


3. flatMap()方法中的mapper是什么?

  1. 数据类型
  2. 方法参数
  3. 以上全部

答案:3)

解释: 这是一个参数,是一个非干涉、无状态的函数,应用于每个元素。它产生一个新值流。


4. 关于flatMap()方法,以下哪项是正确的?

  1. 它是一种终止操作。
  2. 它用于将多个流合并为一个。
  3. 它将每个元素转换为一个流,并将它们合并成一个单一的流。
  4. 它用于并行处理。

答案:3)

解释: flatMap()方法将操作应用于映射函数,并提供元素值的流。这意味着在每个元素的每次迭代中,map()方法都会创建一个单独的新流。通过使用扁平化机制,它将所有流合并成一个单一的结果流。


5. 以下哪项是flatMap()方法的有效用例?

  1. 将列表的列表转换为单个列表。
  2. 根据谓词过滤元素。
  3. 对流中的元素进行排序。
  4. 将元素收集到映射中。

答案:1)

解释: flatMap()方法的使用场景包括:

  • 文本文件的单词计数。
  • 将嵌套列表转换为单个列表。
  • 将嵌套数组转换为单个列表