温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java Set如何保证唯一

发布时间:2026-07-24 11:45:24 来源:亿速云 阅读:99 作者:小樊 栏目:编程语言

在 Java 中,Set 能保证元素唯一,核心原理是:依赖元素的 equals() 和 hashCode() 方法(或 Comparable / Comparator 的比较规则)来去重。不同 Set 实现的具体机制略有差异。

下面按常见 Set 实现逐一说明。


一、总体结论

Set 实现 保证唯一的方式
HashSet hashCode() + equals()
LinkedHashSet 同 HashSet
TreeSet Comparable / Comparator(比较结果为 0 即认为相同)
EnumSet 枚举天然唯一

二、HashSet 如何保证唯一(最常见)

1️⃣ 底层结构

  • 基于 HashMap
  • Set 的元素作为 HashMap 的 key
  • value 是一个固定的 PRESENT 对象
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();

2️⃣ 添加元素流程(add)

public boolean add(E e) {
    return map.put(e, PRESENT) == null;
}

HashMap.put(key, value) 的规则:

  • 如果 key 已存在 → 覆盖 value,返回旧 value
  • 如果 key 不存在 → 插入,返回 null

因此:

  • map.put(e, PRESENT) == null → 表示 之前没有该元素
  • 否则 → 元素已存在,不会重复添加

3️⃣ 判断“相同”的依据

必须同时满足:

  1. hashCode() 相同(或 hash 冲突)
  2. 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);
    }
}

三、LinkedHashSet 如何保证唯一

  • 继承 HashSet
  • 底层仍然是 HashMap
  • 额外维护一个 双向链表 保证插入顺序
  • 唯一性机制与 HashSet 完全相同

四、TreeSet 如何保证唯一(不一样)

1️⃣ 底层结构

  • 基于 TreeMap
  • 使用 红黑树

2️⃣ 判断唯一的方式

不是 equals() / hashCode()

而是:

  • Comparable.compareTo()
  • 或 Comparator.compare()

只要比较结果返回 0,就认为是同一个元素

TreeSet<Integer> set = new TreeSet<>();
set.add(1);
set.add(1);
System.out.println(set.size()); // 1

3️⃣ 注意点(非常重要)

❌ 错误示例:

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() 逻辑一致,否则会出现逻辑错误。


五、EnumSet(特殊)

  • 只用于 enum
  • 内部使用 位向量
  • 枚举常量天然唯一
  • 效率极高
enum Color { RED, GREEN, BLUE }

Set<Color> set = EnumSet.of(Color.RED, Color.RED);
System.out.println(set.size()); // 1

六、常见坑总结

❌ 1. 只重写 equals,不重写 hashCode

@Override
public boolean equals(Object o) {
    return true;
}
// 没重写 hashCode → HashSet 去重失败

❌ 2. 可变对象作为 Set 元素

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 去重流程图 或结合 面试常问点 再讲一遍。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手