distinct()去重依赖equals()和hashcode(),自定义类需重写二者;按字段去重可用tomap实现;它是有状态中间操作,保持原顺序但需注意内存占用。

Java 中用 distinct() 去重最简单直接,但它依赖元素的 equals() 和 hashCode() 方法。如果对象没正确重写这两个方法,distinct() 会失效。
基础用法:对基本类型或已重写 equals/hashCode 的对象去重
对于 String、Integer 等内置类型,或你自己定义且已重写 equals() 和 hashCode() 的类,直接调用 distinct() 即可:
List<string> list = Arrays.asList("a", "b", "a", "c");
list.stream().distinct().collect(Collectors.toList()); // [a, b, c]</string>
自定义对象去重:必须重写 equals 和 hashCode
比如有个 User 类,只按 id 判断是否重复:
public class User {
private Long id;
private String name;
// 构造、getter 省略
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
之后流中调用 distinct() 才能按 id 正确去重。
按某字段去重(不改 equals):用 Collectors.toMap 或 LinkedHashMap
若不想修改类的 equals(),又想按某个字段(如 name)去重,可以用 Collectors.toMap 保留首次出现的元素:
- 用
toMap(key, value, merge),key 是去重依据,value 是整个对象,merge 保留第一个 - 再用
values().stream().collect(...)提取结果
List<user> users = ...;
List<user> uniqueByName = users.stream()
.collect(Collectors.toMap(
User::getName,
Function.identity(),
(u1, u2) -> u1 // 冲突时保留第一个
))
.values()
.stream()
.collect(Collectors.toList());</user></user>
注意点:distinct 是中间操作,且有状态
distinct() 需要内部缓存已见过的元素,所以:
- 它不是无状态操作,不能并行流中随意优化(但并行流仍支持,只是性能可能不如预期)
- 对大数据量要注意内存占用,尤其是对象大、重复少的情况
- 顺序保持:
distinct()保留第一次出现的元素,顺序与原流一致
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











