hashset能自动去重因其底层基于hashmap,add时通过hashcode()和equals()判断重复;自定义类需重写这两个方法;若需有序去重应选linkedhashset。

Java 中用 HashSet 去重最直接的方式就是把数据添加到 HashSet 实例中,它会自动忽略重复元素,因为其底层基于哈希表,不允许重复键(即重复对象)。
为什么 HashSet 能自动去重
HashSet 内部使用 HashMap 存储元素,每个元素作为 HashMap 的 key。当调用 add() 方法时,会先计算对象的 hashCode(),再结合 equals() 判断是否已存在相同元素。只有两个方法都满足“同一对象”逻辑,才视为重复。
- 自定义类去重时,必须重写
hashCode()和equals() - 对于
String、Integer等 JDK 内置类型,已默认实现,可直接使用 - 注意:
HashSet不保证插入顺序,如需有序去重,考虑LinkedHashSet
基础去重示例(字符串/基本类型)
适用于 List 中存的是不可变对象或 JDK 常见类型:
List<string> list = Arrays.asList("a", "b", "a", "c", "b");
Set<string> uniqueSet = new HashSet(list);
List<string> uniqueList = new ArrayList(uniqueSet); // 转回 List(顺序不保证)</string></string></string>
如果希望保留原始顺序,改用 LinkedHashSet:
Set<string> uniqueSet = new LinkedHashSet(list); // 插入顺序被保留</string>
自定义对象去重(关键!)
比如有一个 User 类,按 id 去重:
public class User {
private Long id;
private String name;
public User(Long id, String name) {
this.id = id;
this.name = name;
}
@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);
}
}
之后即可正常使用:
List<user> users = Arrays.asList(
new User(1L, "Alice"),
new User(2L, "Bob"),
new User(1L, "Alice2") // id 相同,会被去重
);
Set<user> uniqueUsers = new HashSet(users); // 最终只保留一个 id=1 的 User</user></user>
一行流式去重(Java 8+)
配合 Stream API,简洁高效:
List<string> uniqueList = list.stream()
.distinct()
.collect(Collectors.toList());</string>
注意:distinct() 内部正是基于 HashSet 实现的,所以同样依赖 hashCode/equals 正确性。
不复杂但容易忽略细节,核心就三点:选对集合类型、确保对象能正确比较、理解顺序与线程安全限制(HashSet 非线程安全,多线程场景请用 Collections.synchronizedSet() 或 ConcurrentHashMap.newKeySet())。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











