hashset的add()返回false说明元素已存在,其依赖hashmap的put(),通过hashcode()定位桶、equals()判断重复;自定义类必须同时一致重写hashcode()和equals(),否则会导致重复或丢失。

HashSet 的 add() 方法返回 false,说明元素已存在,即发生了重复。它内部依赖 HashMap 的 put() 行为,本质是通过对象的 hashCode() 和 equals() 判断是否重复。
add() 返回值的含义
该方法声明为 boolean add(E e):
- 返回 true:元素首次加入,集合大小增加 1;
- 返回 false:元素已存在(根据 equals + hashCode 判定),未添加,集合大小不变。
底层如何判断重复
HashSet 底层用 HashMap 存储,调用的是 map.put(e, PRESENT) == null:
- 先计算元素
e.hashCode(),定位到哈希桶; - 若桶中无元素,直接插入,返回 null → add() 返回 true;
- 若桶中有元素,逐个调用
e.equals(已有元素); - 一旦 equals 返回 true,认为重复,put() 返回旧值(非 null)→ add() 返回 false。
关键前提:正确重写 hashCode 和 equals
如果只重写 equals 而不重写 hashCode,或两者逻辑不一致,会导致:
- 相同对象算出不同 hash,被分到不同桶 → equals 永远不被调用 → 重复元素被错误加入;
- 不同对象算出相同 hash 却 equals 返回 true → 被误判为重复。
所以自定义类放入 HashSet 前,必须同时、一致地重写这两个方法。
常见误用场景
例如:
- 用可变字段(如 name、age)参与 equals/hashCode 计算,之后修改字段 → 可能导致“找不回”或“重复添加”;
- 使用未重写 equals/hashCode 的普通对象(如 new Object())→ 默认基于内存地址,每次都是新元素;
- 混用 null 和空字符串等易混淆值,但 equals 逻辑没覆盖边界情况。
不复杂但容易忽略。










