爱问面试题:==和equals()和Hashcode()三者的理解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爱问面试题:==和equals()和Hashcode()三者的理解相关的知识,希望对你有一定的参考价值。
重写前:* ==表示两个对象的内存地址
* equals()也表示对象内存地址
* hashCode()表示该对象在JVM中的32位内存地址
重写后:
==仍表示两个对象的内存地址
equals()表示连个对象的值是否相等,相等就视为同一个对象
如果equals()方法重写,那么hashCode()方法也要重写,因为要保证同一个对象的hashCode值相等这样的规定。
根据javaAPI文档上的介绍:
(1)、同一个对象的hashCode值一定相同,无论是否重写过equals()方法,也就是说重写过以后他们的值相等了,那么他们的hashCode也要保持相等,所以就也要重写hashCode()方法。
(2)、如果两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
比如重写后的hashCode方法如下:
@Override
?? ?public int hashCode() {
?? ??? ?final int prime = 31;
?? ??? ?int result = 1;
?? ??? ?result = prime * result + age;
?? ??? ?result = prime * result + ((name == null) ? 0 : name.hashCode());
?? ??? ?result = prime * result + sex;
?? ??? ?return result;
?? ?}
比较两个对象是否相等:
(1)先比较连个对象的hashCode值是否相等,如果相等则比较(2)(因为不同的对象也有可能hashCode值相等),如果不等则一定不是同一个对象
(2)再比较equals()方法,如果相等则视为同意对象,反之则不是同一个对象。**
2、hashCode()和equals()关系是什么?
明白几个原则:
equals相等的两个对象,hashcode一定相等。
equals不相等的两个对象,hashcode不一定不相等。
hashcode不相等,那么equals是一定不等的。
hashcode相等,equals可能相等,也可能不等。
解释下第四个原则:
就好比hashcode像是一个词典目录里的按字母为索引查找字,查一个“Z”拼音开头的词,下面等查到“自己”,“自我”,“知道”等词,用equals就是判断这些词语当中是否有相等的词,“自己”和“知道”两个词不相等的,所以equals值不等,但它们同属于"Z"开头的词所以它们hashcode值相等。
3、为什么重写equals的同时也要重写hashCode呢?
hash算法是为了提高equals比较的效率而被发明出来的。这点在集合方面就能体现出来,就比如在List或Set集合里要比较是否有重复元素,当发现某个集合对象与另一个集合对象equals比较的结果相等时,则停止查找返回true值,反之,返回false值。
但如果集合中有大量元素呢,假设一个集合A里有10万元素,而且另一个比较的对象B中还可能没有重复的值,则意味着其实不用比较我都知道两者不相同,但程序依然会对集合A里遍历10万元素然后和B进行逐一排查。。。又或者当我要加入第100001个数据我要验证前面元素有重复值,就要跟前面10万个元素一一比较,效率可想而知很低。
而哈希算法就是Java系统首先调用对象的hashCode()方法获得该对象的哈希码表,然后根据哈希码找到相应的存储区域,若哈希码相同在取得该存储区域内的每个元素与该对象进行equals方法比较,若不同也就没有继续比较的必要了,这对于数量较大的情况效率就提高了不少,重写hashcode方法,最主要就是保证操作的元素在同一个对象里且值都没有重复,若没有重写hashcode,可能会出现将对象引用不同,但元素完全相同的集合进行操作。
下面写一个例子
package demo;
public class override_HshCode_Equals {
public int x;
public int y;
public override_HshCode_Equals(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
//下面变量初始化值可以任意取
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
/**
* equals返回false就说明没有重复项可以添加
* true是重复不能添加
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final override_HshCode_Equals heClass = (override_HshCode_Equals) obj;
//这里就对实例化对象里的x,y进行比较
if (x != heClass.x) {
return false;
}
if (y != heClass.y) {
return false;
}
return true;
}
}
测试类
package demo;
import java.util.HashSet;
public class TestMain {
public static void main(String[] args) {
HashSet<override_HshCode_Equals> set = new HashSet<override_HshCode_Equals>();
override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1);
override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5);
override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1);
set.add(heClass1);
set.add(heClass2);
set.add(heClass3);
set.add(heClass1);
System.out.println("set数量=" + set.size());
}
}
结果如下
set数量=2
注:重写override_HshCode_Equals类的hashCode相当于自定义返回了一个“哈希码”,对比x,y值是否相等,先比较hashcode值,heClass1(3,3)==heClass3(3,3),所以它们的hashcode值相等,但是heClass2的x,y和heClass1,heClass3的x,y值不等,所以hashcode不等,equals一定不等,所以heClass2对象是可以add进去的。前面说了heClass1和heClass3的hashcode值相等,然后进入equals进行对比,发现两者的对象都是相同的,根据程序add循序来看,所以heClass1是可以add进去的,然后heClass3和后面add(heClass1)都为重复项,就不会添加
以上是关于爱问面试题:==和equals()和Hashcode()三者的理解的主要内容,如果未能解决你的问题,请参考以下文章