Set 如何保证元素不重复的?
2026/6/6 6:25:57 网站建设 项目流程

💡 核心结论:一句话先记住

以最常用的 HashSet 为例,它自己其实是个“甩手掌柜”,底层完全是靠一个 HashMap 在帮它干活。它把你要存的元素当成 HashMap 的Key塞进去,利用“HashMap 的 Key 绝对不能重复”的铁律,顺理成章地实现了去重。


🔍 HashSet 存东西时的“两步判重法”

当你往 HashSet里执行add(元素)存东西时,底层的 HashMap 会像小安检员一样,进行以下两步高效率的检查:

第一步:对暗号(算hashCode

安检员先拿这个元素算出一个数字暗号(哈希值)。

  • 如果这个暗号在格子里从来没出现过,说明是新面孔,直接放行通过,成功存入!
  • 如果发现有人的暗号一模一样(哈希冲突),别着急,它不会马上拒绝,而是启动第二步。

第二步:验真身(比equals

因为不同东西的暗号偶尔也会撞款,安检员会把这两个暗号相同的东西揪出来,用equals()方法进行精细的“肉眼比对”:

  • 比对完发现内容确实不一样:行吧,那也是新东西,找个位置存进去。
  • 比对完发现内容完全一样:好家伙,真的是复制品!HashSet会直接把新来的拒之门外,返回false(但不会报错)。

💡 为什么非要分两步?

因为hashCode()是数字比较,计算机算起来极其飞快,能瞬间过滤掉 99% 的不重复元素;而equals()就像做全身扫描,比较慢。先用第一步大面积筛选,性能才能起飞。


🛑 工作和面试中的超级大坑

坑:只重写equals(),不重写hashCode()

如果你写了一个“自定义对象”(比如用户类),只重写了equals没重写hashCode,那 [HashSet] 的去重功能就会直接瘫痪

因为两个一模一样的对象,算出来的暗号(hashCode)却不一样,它们会直接在第一步被分到不同的格子里,连互相见面的机会都没有,equals根本不会执行。结果就是 [Set] 里塞进去了两个完全一样的数据。


🆚 常见的三个 Set 兄弟对比

Set 实现类底层靠谁怎么判重出来的顺序速度
HashSet(盲选首选)HashMaphashCode+equals完全无序(随机乱坐)🚀 极快
LinkedHashSetLinkedHashMaphashCode+equals先进先出(怎么放进去就怎么出来)🏎️ 快
TreeSetTreeMapcompareTo()比较大小自动从小到大排序🚗 一般

🎯 秒记口诀

HashSet 底层 HashMap,元素做 Key 占住位。

先比 hash 快速筛,再比 equals 验真伪。

想要去重不失效,两个方法齐重写!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询