最近在看《Head First
Java》,看到了HashSet如何检查重复,是通过如下代码逻辑,先使用hashCode()快速定位,然后在通过equals来判断是否为相同对象。
if (class1.hashCode() == class2.hashCode() && class1.equals(class2)) {}
然后对hashcode不同,为什么对象可能相同产生了疑惑,书中解释如下,在书的第563页。

问:为什么不同对象会有相同hashcode的可能?

:HashSet使用hashcode来达成存取速度较快的存储方法。如果你尝试用对象来寻找ArrayList中相同的对象(也就是不用索引来找),ArrayList会从头开始找起。但HashSet这样找对象的速度就快多了,因为它使用hashcode来寻找符合条件的元素。因此当你想要寻找某个对象时,通过hashcode就可以很快地算出该对象所在的位置,而不必从头一个一个找起。

     数据结构的课程绝对会告诉你更完整的理论,但这样说明也能让你知道如何有效率地运用HashSet。事实上,如何开发出有效率的杂凑算法一直都是博士论文的热门题目。

     重点在于hashcode相同并不一定保证对象是相等的,因为hashCode()所使用的杂凑算法也许刚好会让多个对象传回相同的杂凑值。越糟糕的杂凑算法越容易碰撞,但这也与数据值域分布的特性有关。总而言之,把数据结构这科目搞定就对了。
     如果HashSet发现在比对的时候,同样的hashcode有多个对象,它会使用equals()来判断是否有完全的符合。
也就是说,hashcode是用来缩小寻找成本,但最后还是要用equals()才能认定是否真的找到相同的项目。

hashCode()与equals()的相关规定
API文件有对对象的状态制定出必须遵守的规则:
(1)如果两个对象相等,则hashcode必须也是相等的。
(2)如果两个对象相等,对其中一个对象调用equals()必须返回true。也就是说,若a.equals(b)则b.equals(a)。
(3)如果两个对象有相同的hashcode值,它们也不一定是相等的。但若两个对象相等,则hashcode值一定是相等的。
(4)因此若equals()被覆盖过,则hashCode()也必须被覆盖。
(5)hashCode()的默认行为是对在heap上的对象产生独特的值。如果你没有override过
hashCode(),则该class的两个对象怎样都不会被认为是相同的。

(6)equals()的默认行为是执行==的比较。也就是说会去测试两个引用是否对上heap上同一个对象。如果equals()没有被覆盖过,两个对象永远都不会被视为相同的,因为不同的对象有不同的字节组合。

a.equals(b)必须与a.hashCode() == b.hashCode()等值
但a.hashCode() == b.hashCode()不一定要与a.equals()等值。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信