hashset完全基于hashmap封装实现,内部以元素为key、共享静态对象present为value;add/contains/remove等操作均委托给hashmap对应方法,复用其哈希机制与性能保障。

Java 中的 HashSet 并不是独立实现的哈希表,而是**完全基于 HashMap 封装而成**——它内部持有一个 HashMap 实例,把元素作为 key 存入,而 value 固定使用一个共享的、无意义的静态对象(PRESENT)。
为什么用 HashMap 实现 HashSet?
因为 HashSet 的核心需求是:快速去重、O(1) 平均时间复杂度的添加/查找/删除。而 HashMap 天然满足这些——它通过哈希码定位桶、用 equals 判断重复。只需忽略 value,只关注 key 的唯一性,就自然得到了 set 语义。
HashSet 不需要存储额外值,所以 value 统一设为:
add() 方法如何工作?
调用 HashSet.add(e) 时,实际执行的是:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 将元素
e作为 key,PRESENT作为 value,调用底层map.put(e, PRESENT) -
HashMap.put()返回null表示该 key 之前不存在 → 添加成功,add()返回true - 若返回旧 value(即
PRESENT),说明 key 已存在 → 不重复添加,add()返回false
contains() 和 remove() 同理
它们分别委托给 HashMap.containsKey() 和 HashMap.remove():
-
contains(e)→ 检查 map 中是否存在 key 为e的映射 -
remove(e)→ 删除 key 为e的条目,返回是否删除成功(即原 map 中是否存在该 key)
所有逻辑复用 HashMap 的哈希计算、桶定位、链表/红黑树查找等机制,零重复代码。
迭代器和容量控制也依赖 HashMap
HashSet.iterator() 返回的是 HashMap.keySet().iterator(),遍历的其实是 keySet 视图;size() 直接返回 map.size();构造时传入的 initialCapacity 和 loadFactor,最终都用于初始化内部的 HashMap 实例。
所以,HashSet 是典型的「组合优于继承」实践——不继承 HashMap,而是持有它,专注提供 set 接口,底层能力全由 HashMap 承担。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










