hashset自动去重的核心是底层用hashmap存储,元素作key、固定object作value;依赖hashcode()和equals()判断重复,二者需合理重写;允许一个null;非线程安全,遍历时修改会抛concurrentmodificationexception。

HashSet 自动去重的核心在于它底层使用 HashMap 存储元素,而 HashMap 的 key 不允许重复——HashSet 把所有元素都当作 key 存进 HashMap,value 统一用一个固定的 Object 实例(如 PRESSENT)占位。只要元素的 hashCode() 和 equals() 方法实现合理,就能正确识别重复。
依赖 hashCode() 和 equals() 判断重复
HashSet 在添加元素时,先计算该元素的 hashCode(),定位到哈希桶位置;如果桶中已有元素,再逐个调用 equals() 比较。只有两个方法都一致,才视为重复。
- 若自定义类未重写
hashCode()和equals(),默认继承自 Object,此时每个对象 hash 值不同、equals 返回 false,即使内容相同也会被当作不同元素存入 - 字符串、Integer 等 JDK 内置类已正确重写这两个方法,可直接用于 HashSet 去重
- 重写时需保证:相等的对象必须返回相同 hash 值;hash 值相同的对象,
equals()不一定为 true(即允许哈希冲突,但不能漏判相等)
添加过程不报错,重复元素直接忽略
调用 add(E e) 方法时,如果元素已存在,HashSet 不抛异常,也不覆盖,而是静默返回 false;成功添加才返回 true。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
Set<string> set = new HashSet();</string>set.add("a"); // 返回 trueset.add("a"); // 返回 false,集合仍只含一个 "a"
注意 null 元素的特殊处理
HashSet 允许且仅允许存储一个 null 值。因为 null.hashCode() 会抛空指针,所以内部做了单独判断:遇到 null 时,直接在哈希表第一个桶(index 0)查找是否存在 null key。
set.add(null); // 成功set.add(null); // 失败,返回 false- 多次添加
null不影响集合大小,也不会报错
不是线程安全,多线程需额外保护
HashSet 本身没有任何同步机制。多个线程同时写入可能破坏内部结构(如链表成环),导致死循环或数据丢失。
- 可用
Collections.synchronizedSet(new HashSet())包装 - 或直接使用
ConcurrentHashMap.newKeySet()(Java 8+),它是线程安全的 Set 实现 - 避免在遍历过程中修改集合,否则会触发
ConcurrentModificationException
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










