Java 8 Stream.distinct() 方法

10 Sept 2024 | 4 分钟阅读

Java 8 的 distinct() 操作 主要与流(stream)相关,用于从流中删除重复的元素。Stream API 是在 Java 8 中引入的,它提供了一种更实用的与集合交互的方式,distinct() 操作就是其中的一部分。

语法

distinct() 方法的目的

distinct() 操作通过从流中删除重复的元素,确保结果中每个元素只出现一次。

distinct() 方法的应用

1. 简单类型

在处理简单类型(如整数和字符串)时,distinct() 基于它们的相等性或自然顺序来比较元素。

2. 对象

对于自定义对象,distinct() 操作使用对象的 equals() 方法来确定相等性。

distinct() 方法的工作原理

  1. distinct() 操作是一个有状态的中间操作。它在流处理过程中使用一个集合(或类似数据结构)来记录迄今为止遇到的唯一元素。
  2. 当元素通过流时,distinct() 操作会检查每个元素是否已存在于集合中。如果存在,该元素将被过滤掉,被视为重复项。

下面我们将通过完整的代码示例,来了解 Java 8 的 distinct() 操作的各种用法。

1. 在 Java Stream 中使用 distinct() 方法

在 Java Stream 中,可以使用 distinct() 方法从元素流中去除重复项。

Distinct.java

输出

List: [1, 2, 3, 4, 2, 3, 5, 6, 7, 8, 1]
Distinct elements of the list: [1, 2, 3, 4, 5, 6, 7, 8] 

解释

我们创建一个包含一些重复项的整数(数字)列表。使用 stream() 方法从列表中创建流。然后,流经过 distinct() 操作以去除重复项。最后,使用 collect(Collectors.toList()) 函数将流中的元素收集到一个新列表(distinctNumbers)中,并打印原始列表和去重后的列表。

2. 使用 distinct() 方法处理对象

如果我们有一个自定义对象列表,并希望根据特定属性删除重复项,则可以结合使用 distinct() 和自定义比较器。

DistinctObjects.java

输出

Original List: [Person@6956de9, Person@769c9116, Person@6aceb1a5, Person@2d6d8735]
Distinct List: [Person@6956de9, Person@769c9116, Person@6aceb1a5, Person@2d6d8735]

解释

我们创建一个包含一些重复项的 Person 对象列表,这些对象基于姓名和年龄数据。使用 stream() 函数将列表转换为 Person 对象流。使用默认的对象相等性检查(即 equals() 方法),distinct() 函数用于去除重复项。然后打印原始列表和去重后的列表,结果被收集到一个新列表(distinctPeople)中。

3. 使用 distinct() 方法处理复杂对象

我们可以将 distinct() 与其他流操作结合使用,以处理更复杂的情况。

DistinctFlatMap.java

输出

Nested Lists: [[11, 22, 23], [22, 13, 24], [13, 34, 25]]
Distinct Numbers in Nested Lists: [11, 22, 23, 13, 24, 34, 25] 

解释

使用 stream() 方法将列表的列表转换为列表流。使用 flatMap(List::stream) 函数将嵌套列表展平成一个单一的整数流。通过 distinct() 技术实现重复数字的去除。当结果被收集到一个新列表(distinctNumbers)中时,将报告原始嵌套列表和去重后的数字。

结论

总而言之,在函数式编程范式中,Java 8 Stream 中的 distinct() 方法是消除重复并保证唯一性的有用工具。它具有适应性,适用于不同类型的数据,并且其状态性被限制在操作内部,保持了流管道的整体无状态性。必须正确实现相等性测试,开发者还必须考虑性能,尤其是在处理大型或复杂数据集时。distinct() 操作是清理、预处理和维护数据集或流完整性的可行方法。