跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

在Java里HashSet是如何保证不重复的_HashSet原理解析

HashSet通过HashMap的键唯一性实现去重,将元素作为key、PRESENT作value存储;判断重复需hashCode()与equals()共同作用,自定义类须重写二者;底层调用map.put(e, PRESENT)并依据返回值是否为null判定添加成功。 HashSet靠HashMap的键唯一性实现去重 HashSet本身不直接管理元素是否重复,而是把所有元素作为内部HashMap的key来存储,value统一用一个空对象(PRESENT)占位。因为HashMap规定同一个key只能存在一份,所以只要元素能被正确识别为“同一个key”,就不会重复添加。 判断重复依赖hashCode和equals两个方法 往HashSet里add一个对象时,会按以下顺序判断: 先调用该对象的
hashCode()
,算出哈希值,定位到哈希表中某个桶(数组位置) 如果桶为空,直接存入 如果桶已有元素,就逐个调用
equals()
比较——只有当
hashCode()
相同 且
equals()
返回true,才认定是重复元素,跳过添加 注意:自定义类(比如Student)若想在HashSet中正确去重,必须同时重写
hashCode()
和
equals()
,否则默认按内存地址比较,两个内容相同的对象也会被当成不同元素。 底层操作其实就是HashMap.put() 看源码就能确认这一点: Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 立即学习 “ Java免费学习笔记(深入) ”;
HashSet.add(e)
内部调用的是
map.put(e, PRESENT)
而
HashMap.put()
在发现key已存在时,会用新value覆盖旧value,并返回旧value;如果key不存在,则返回null 所以HashSet的add方法靠
put(...) == null
来判断是否真正新增成功 无序、允许null、线程不安全是附带特性 这些不是去重机制本身决定的,而是由底层HashMap行为自然带来的: 无序:哈希值决定存放位置,和插入顺序无关 允许一个null:HashMap允许key为null,且只允许一个(null的hashCode固定为0) 线程不安全:HashMap非同步,多个线程同时add可能引发数据错乱或丢失

相关文章