在 Java 中,Set 能保证元素唯一,核心原理是:依赖元素的 equals() 和 hashCode() 方法(或 Comparable / Comparator 的比较规则)来去重。不同 Set 实现的具体机制略有差异。
下面按常见 Set 实现逐一说明。
| Set 实现 | 保证唯一的方式 |
|---|---|
HashSet |
hashCode() + equals() |
LinkedHashSet |
同 HashSet |
TreeSet |
Comparable / Comparator(比较结果为 0 即认为相同) |
EnumSet |
枚举天然唯一 |
HashMapSet 的元素作为 HashMap 的 keyPRESENT 对象private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
HashMap.put(key, value) 的规则:
null因此:
map.put(e, PRESENT) == null → 表示 之前没有该元素必须同时满足:
hashCode() 相同(或 hash 冲突)equals() 返回 true⚠️ 如果只重写其中一个,会导致 去重失败
✅ 正确示例:
class User {
private int id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return id == user.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
HashSetHashMapTreeMap不是 equals() / hashCode()
而是:
Comparable.compareTo()Comparator.compare()只要比较结果返回 0,就认为是同一个元素
TreeSet<Integer> set = new TreeSet<>();
set.add(1);
set.add(1);
System.out.println(set.size()); // 1
❌ 错误示例:
class User implements Comparable<User> {
int id;
public int compareTo(User o) {
return 0; // 所有对象都相等
}
}
✅ 正确示例:
public int compareTo(User o) {
return Integer.compare(this.id, o.id);
}
⚠️ compareTo() 必须与 equals() 逻辑一致,否则会出现逻辑错误。
enumenum Color { RED, GREEN, BLUE }
Set<Color> set = EnumSet.of(Color.RED, Color.RED);
System.out.println(set.size()); // 1
@Override
public boolean equals(Object o) {
return true;
}
// 没重写 hashCode → HashSet 去重失败
Set<List<Integer>> set = new HashSet<>();
List<Integer> list = new ArrayList<>();
set.add(list);
list.add(1); // 修改对象
set.contains(list); // 可能 false
✅ 解决:
Set 保证唯一,不是靠 Set 自己,而是靠元素对象的“相等规则”
HashSet→hashCode()+equals()TreeSet→compareTo()/compare()EnumSet→ 枚举天然唯一
如果你愿意,我可以帮你画一张 HashSet 去重流程图 或结合 面试常问点 再讲一遍。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。