javastream的distinct
时间: 2025-05-29 17:31:01 浏览: 15
<think>好的,用户现在想了解Java Stream中的distinct方法的使用示例。让我先回顾一下之前的对话历史,确保回答的一致性。之前用户问过如何判断数组为空,我详细给出了不同语言的实现方法,其中Java部分提到了检查null和length。现在用户的问题转向Java Stream的distinct方法,需要结合他们提供的三个站内引用。
首先,用户提供的引用[1]详细解析了distinct方法,提到它基于equals方法判断重复。引用[2]是关于LongStream的distinct,说明其适用于原始类型流。引用[3]给出了一个字符串去重的示例代码。用户的需求是使用示例,所以需要结合这些引用,给出具体的代码案例,并覆盖对象去重、自定义对象的处理,以及可能的多字段去重方法。
接下来,我需要确保回答结构清晰,符合用户要求的系统指令,比如行内数学公式用$...$,但这里可能用不上。需要分点回答,包含基本使用、对象去重、多字段处理、性能注意事项等。同时,要生成相关问题,帮助用户深入理解。
用户可能想知道如何正确使用distinct,特别是对于自定义对象,因为默认的equals和hashCode可能不满足需求,需要重写。另外,用户可能对性能有疑问,比如distinct在并行流中的表现,或者与其他操作结合时的顺序影响。还有,引用中提到LongStream的distinct,可能需要说明原始类型流的使用。
需要注意回答中引用文献的位置,比如在提到equals方法时引用[1],提到LongStream时引用[2],示例代码部分引用[3]。同时,要确保代码示例正确,比如自定义对象的例子需要展示重写equals和hashCode,或者使用包装类的方法。
最后,生成的相关问题需要围绕distinct的深入使用,比如与sorted的区别、并行流中的表现、自定义比较器的替代方案等。这样用户可以根据问题进一步探索。</think>### Java Stream中`distinct()`方法详解与示例
`distinct()`是Java Stream API中用于去重的核心方法,其底层通过`equals()`方法判断元素唯一性[^1]。以下从**基础用法**到**复杂场景**分层次说明,并提供完整代码示例。
---
### 一、基础用法:简单类型去重
#### 1. 字符串去重(引用示例优化)
```java
List<String> words = Arrays.asList("apple", "banana", "apple", "orange");
List<String> uniqueWords = words.stream()
.distinct()
.collect(Collectors.toList());
// 输出:[apple, banana, orange]
```
- **原理**:直接依赖`String.equals()`方法比较重复项[^3]。
#### 2. 数值类型去重(含`LongStream`)
```java
LongStream numbers = LongStream.of(5L, 3L, 5L, 7L);
long[] uniqueNumbers = numbers.distinct().toArray();
// 输出:[5, 3, 7]
```
- **特性**:`LongStream.distinct()`针对原始类型优化内存占用[^2]。
---
### 二、对象去重:自定义类处理
#### 1. 依赖默认`equals()`方法(需重写)
```java
class Product {
private String id;
public Product(String id) { this.id = id; }
@Override
public boolean equals(Object o) {
return o instanceof Product && ((Product)o).id.equals(this.id);
}
@Override
public int hashCode() { return id.hashCode(); }
}
List<Product> products = Arrays.asList(
new Product("P1"), new Product("P2"), new Product("P1")
);
List<Product> uniqueProducts = products.stream()
.distinct()
.collect(Collectors.toList());
// 输出:两个不同对象(P1被去重)
```
- **关键点**:必须重写`equals()`和`hashCode()`[^1]。
#### 2. 无`equals()`覆盖时的替代方案
若无法修改类代码,可用**包装类+自定义属性提取**:
```java
List<Product> uniqueByName = products.stream()
.map(p -> new AbstractMap.SimpleEntry<>(p.getId(), p))
.distinct()
.map(Entry::getValue)
.collect(Collectors.toList());
```
---
### 三、复合条件去重(多字段判断)
通过`TreeSet`自定义比较器实现多字段去重:
```java
List<Employee> employees = Arrays.asList(
new Employee("Alice", 30),
new Employee("Bob", 25),
new Employee("Alice", 30)
);
List<Employee> uniqueEmployees = employees.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() ->
new TreeSet<>(Comparator.comparing(e -> e.getName() + "|" + e.getAge()))
), ArrayList::new
));
// 根据姓名和年龄组合去重
```
---
### 四、性能与注意事项
| 场景 | 建议 |
|---------------------|----------------------------------------------------------------------|
| **大数据量** | 先使用`filter`或`limit`缩小数据集,再调用`distinct()`[^1] |
| **并行流** | `distinct()`会合并所有子流数据,可能增加内存压力 |
| **有序流** | 若输入流已排序,`distinct()`会保留首个出现项(与SQL行为不同) |
---
### 完整对比示例
```java
// 原始数据:[A, B, A, C]
List<String> result = Arrays.asList("A", "B", "A", "C").stream()
.distinct()
.sorted()
.collect(Collectors.toList());
// 输出:[A, B, C]
```
- **操作顺序影响**:`distinct()`与`sorted()`的调用顺序可能改变最终结果。
---
阅读全文
相关推荐


















