HashSet通过HashMap的key唯一性实现去重,add(e)调用map.put(e, PRESENT),返回null表示新增成功,否则为重复;要求元素正确重写hashCode和equals以保证去重生效。

HashSet 通过哈希表(HashMap)的 key 存储机制天然实现去重,不存重复元素。它内部不直接操作哈希表数组,而是用一个统一的虚拟值 PRESSENT 作为所有 key 对应的 value,把“是否包含该元素”完全交给 HashMap 的 key 唯一性保证。
底层是 HashMap,元素作 key,固定值作 value
HashSet 源码中,实际持有 private transient HashMap
map.put(e, PRESENT),其中 PRESENT 是一个静态 final Object(如 new Object())。
因为 HashMap 不允许 key 重复,当 put 相同 key 时,新 value 替换旧 value,但返回旧 value —— HashSet 就靠这个返回值是否为 null 来判断是否新增成功。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
add 方法如何判断重复
- 调用 map.put(e, PRESENT),如果之前没存过 e,put 返回 null → add 返回 true
- 如果 e 已存在,put 返回原来的 PRESENT 对象(非 null)→ add 返回 false
- 整个过程不依赖 equals() 单独比较,而是由 HashMap 的 put 流程完成:先算 hash,定位桶,再在链表/红黑树中用 equals() 逐个比对
去重生效的两个必要条件
- hashCode() 一致:相同对象必须返回相同哈希值,否则会被分配到不同桶,跳过 equals 检查,导致逻辑重复
- equals() 正确重写:若两个对象业务上相等,equals 必须返回 true;否则即使 hash 相同,也会被当作不同元素存入
小例子:自定义类要能去重,必须重写 hashCode 和 equals
比如 Student 类按 id 去重:
public class Student {private int id;
private String name;
// 构造、getter 省略
@Override
public int hashCode() { return Objects.hash(id); }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id;
}
}
这样 new Student(1,"A") 和 new Student(1,"B") 就算重复,add 时只会留一个。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










