答:因为两个相等的对象的 hashCode值必须是相等。也就是说如果equals方法判断两个对象是相等的,那这两个对象的hashCode值也要相等。
如果重写equals()时没有重写 hashCode()方法的话就可能会导致equals方法判断是相等的两个对象,hashcode值却不相等。
我们知道一旦重写了equals方法,就一定要重写hashCode方法。为什么?
------因为必须保证重写后的equals方法认定相同的两个对象拥有相同的哈希值
------当我们将equals方法重写后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中“相同对象必须有相同哈希值”的约定。
那么怎样去解释这句话?接着往下看。
我们打开Object类的equals方法源码,可以看到有一部分注释是这样写的:
大致意思是:每当重写 equals方法后, hashCode 方法通常也需要重写,以便维护 hashCode 方法的一般协定,该协定声明相等的对象必须具有相等的哈希值。
那为什么要去维护 hashCode 方法的协议呢?找到hashCode方法源码,这里给出了解释:
首先hashCode方法相当于一个哈希函数,将对象的内部地址转换为一个integer类型的哈希值。
hashCode总的契约有三条,分别是:
1、一个对象多次调用他的hashCode应该返回相同的整数(哈希值);
2、如果两个对象根据equals方法判断是相等的,那么这两个对象返回的整数也应该相同;
3、如果两个对象根据equals判断是不相等的,不要求返回不同的整数,但不同的整数结果对应的对象也应该是不同的。
以画图的方式表示这三条契约:
equals方法和hashCode方法两者的关系,总结一下就是:
- 如果两个对象相同(equals返回true),那么他们的hashCode值一定相同;
- 如果两个对象不同(equals返回false),那么他们的hashCode值可能相同可能不同;
- 如果两个对象的hashCode值相同(hash冲突),那么他们可能相同也可能不同(equals方法返回false / true);
- 如果两个对象的hashCode值不同,那么他们肯定不同(equals返回false)。
其实到这里,我们就明白equals方法与hashCode方法是配套使用的。对于任何一个对象,不论是使用继承自Object的equals方法还是重写equals方法。hashCode方法实际上必须要完成的一件事情就是,为该equals方法认定为相同的对象返回相同的哈希值。
⭕还要注意一点就是,当重写equals方法时通常将hashCode方法重写,提高比较效率。
(例如先求hashCode值,如果相等 再使用equals比较,比起用equals挨个比较块且便捷)
以上就是理论内容,下面举个例子:
问题一:我对左侧QueryBO的equals方法和hashCode方法进行了重写,在右边的比较中应该输出什么?
-----true
-----原因:如果不重写equals,那么只有两对象内所有属性都相同才认为相等;而现在我重写了equals,这里只需要对象的query3相等,则认为两对象想等。
问题二:将queryBO1对象和queryBO2放进Set集合,Set集合中有几个对象?
-----1个
-----由于上一步判定两对象相等,而Set集合中的元素是不重复的,所以Set中只有一个元素。
Set<QueryBO> set=new HashSet<>(); set.add(queryBO1); set.add(queryBO2); System.out.println("Set:"+set); //输出 Set:[QueryBO(query1=true, query2=true, query3=false)]
问题三:将代码更改,再次进行上述两步操作,这次的答案又是什么
输出:
Set:[QueryBO(query1=true, query2=true, query3=false), QueryBO(query1=false, query2=true, query3=true)] true
-----为什么equals比较结果为true,但去重集合Set中却有两个元素呢?
-----原因:像HashSet、HashMap这类 判断两对象相不相同先比较的是hashCode( ),equals比较的是query2,而hashCode比较的是query3,hashCode不相等了,所以我们的HashSet也会认为两个对象不相等。
所以注意 重写equals( )一定要重写hashCode( ) !
问题四:字符串的hashCode相等,这两个对象一定相等吗?(hashCode相等的字符串一定相等?)
-----错。hashCode相等两个字符串不一定相等。
-----例子:一下这些字符串的hashCode都一样。