关于hashcode和equals的用法与具体区别,我想通过如下例子引入。
首先,我设计一个HashSetTest类和一个Student类,在HashSetTest中添加4个Student的实例,其中第四个和第一个实例的number和name都一样,所以是相同元素。按照HashSet不能有重复元素的性质,最终输出的答案当中,Student0不会出现两次(第二个Student0作为重复元素被忽略)。
然而。实际的结果却是出乎意料的,最终输出如下:
我们看到,两次Student0都被add进了HashSet当中。原因是什么?我们自己写的Student类并没有重新自己的hashcode()和equals()方法,所以在比较时,是继承的object类中的hashcode()方法,而object类中的hashcode()方法是一个本地方法,比较的是对象的地址(引用地址),使用new方法创建对象,两次生成的当然是不同的对象了,hashcode()的返回原则是:如果地址一样就返回true,不一样就返回false。如此一来,在add时对add的元素进行比较时,由于调用的是未经重写的hashcode(),所以比较的其实是元素的地址,由于第四次add的那个student显然和第一次add的student地址不同,所以hashcode()偷偷返回了false(我们期望它返回true!)。
因此,重写Student类中的equal()和hashcode()就显得非常重要了。
现在进行如下的重写:
再次运行HashSetTest,就得到了预期的结果。
在java的集合中,判断两个对象是否相等的规则是:
1.判断两个对象的hashCode是否相等
如果不相等,两个对象不相等
如果相等,转入2
2.判断两个对象用equals运算是否相等
如果不相等,两个对象不相等
如果相等,两个对象相等(equals()是判断两个对象是否相等的关键)
可以进一步推断出如下的结论:
1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。
2、如果两个对象的hashCode相同,它们并不一定相同。
第一点很好理解,两个相同的对象,他们的哈希码如果不一样,他们在哈希表中就存放在两个不同的位置,这与哈希表无重复元素的性质矛盾。所以他们哈希码必定相同。
第二点,两个对象的哈希码相同,意味着他们存在哈希表的同一个位置,并不能保证他们是相同的。(因为即使他们不同也可以在哈希表的同一个位置用链表连接起来)。