Java中HashSet去重利用其不允许重复元素的特性,直接初始化可自动过滤重复项但不保证顺序;需保序用LinkedHashSet;自定义对象须重写equals和hashCode;Stream.distinct()底层基于LinkedHashSet,兼顾去重与顺序。

Java 中用 HashSet 去重列表,核心是利用其**不允许重复元素**的特性:将列表元素全部添加进 HashSet,重复项会自动被忽略,再转回列表即可。
直接构造 HashSet 去重(推荐)
最简洁的方式是用列表直接初始化 HashSet,它会在构建过程中自动过滤重复元素:
List<String> original = Arrays.asList("a", "b", "a", "c", "b");
Set<String> uniqueSet = new HashSet<>(original);
List<String> uniqueList = new ArrayList<>(uniqueSet); // 若需 List 类型
⚠️ 注意:顺序不保证。HashSet 不维护插入顺序,结果列表元素顺序可能与原列表不同。
保持插入顺序?用 LinkedHashSet
如果需要**去重同时保留首次出现的顺序**,应使用 LinkedHashSet:
立即学习“Java免费学习笔记(深入)”;
- 它继承自
HashSet,同样去重 - 内部用链表维护插入顺序,遍历时按添加顺序返回
List<String> original = Arrays.asList("a", "b", "a", "c", "b");
Set<String> uniqueSet = new LinkedHashSet<>(original);
List<String> uniqueList = new ArrayList<>(uniqueSet); // ["a", "b", "c"]
对自定义对象去重:必须重写 equals() 和 hashCode()
若列表中是自定义类(如 User),仅靠 HashSet 默认行为无法正确去重,因为默认比较的是对象引用。
必须在该类中:
- 重写
equals()方法(定义“两个对象相等”的逻辑,比如 id 相同即相等) - 重写
hashCode()方法(确保相等的对象有相同哈希值,否则HashSet查找失效)
✅ 正确示例(Lombok 可简化):
@Data // Lombok 自动生成 getter/setter/equals/hashCode/toString
public class User {
private Long id;
private String name;
}
// 使用方式不变:
List<User> users = Arrays.asList(new User(1L, "Alice"), new User(1L, "Alice"));
Set<User> uniqueUsers = new HashSet<>(users); // 自动去重(id 相同视为重复)
一行流式写法(Java 8+)
配合 Stream API,可写成链式调用:
List<String> uniqueList = original.stream()
.distinct() // 内部使用 LinkedHashSet 保证顺序和去重
.collect(Collectors.toList());
✅ Stream.distinct() 底层正是基于 LinkedHashSet 实现,既去重又保序,适合函数式风格。


















