引言
在面试题中,关于equals的问题可以说是很常见的了,例如:
1、equals和 == 有什么区别?
2、hashcode相等的两个对象一定==相等吗?equals相等吗?
3、两个对象用equals比较相等,那它们的hashcode相等吗?
关于问题一,我会在博客的末尾附上我的另一篇博客链接。本篇博客重点探究问题二和问题三。
探究
Person 类:
public class Person
{
private String name;
private int age;
private String sex;
public Person(String name, int age, String sex){
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public boolean equals(Object obj)
{
if(obj instanceof Person){
Person person = (Person)obj;
return name.equals(person.name);
}
return super.equals(obj);
}
@Override
public int hashCode()
{
return name.hashCode();
}
}
测试类:
public class HashTest {
public static void main(String[] args)
{
HashMap<Person, Integer> map = new HashMap<Person, Integer>();
Person p = new Person("jack",22,"男");
Person p1 = new Person("jack",22,"男");
System.out.println("p的hashCode:"+p.hashCode());
System.out.println("p1的hashCode:"+p1.hashCode());
System.out.println(p.equals(p1));
System.out.println(p == p1);
map.put(p,888);
map.put(p1,888);
map.forEach((key,val)->{
System.out.println(key);
System.out.println(val);
});
}
}
情况一:二者均不重写
注释掉Person的equals和hashCode,输出
Object 类的 equals 源码
Object 类的 hashCode 源码
由 Object 类的源码以及 hashCode 的计算来源可以得知,它们的表现是一致的,都是比较两个变量的内存地址是否相等。由于这两个方法都没有重写,判定这两个对象是不同的,放在不同的索引之下。(用的都是父类的方法)
情况二:equals重写,hashCode不重写
注释掉Person的hashCode,输出
由上面的结果可知,通过重写的 equals 方法判定,这两个对象应该放在 hash 表的同一个索引之下。但由于我们建了两个不同的对象,得到了两个不同的地址,而且我们没有重写 hashCode 方法,所以这两个对象会放在不同的索引之下。这样的话就会与hash的设计相冲突,导致整个 hash 结构无法正常工作。(子类的equals,父类的hashCode)
情况三:equals不重写,hashCode重写
注释掉Person的equals,输出
这就与情况二类似,通过重写的 hashCode方法判定,这两个对象应该放在 hash 表的同一个索引之下。但由于我们建了两个不同的对象,得到了两个不同的地址,而且我们没有重写 equals 方法,判定这两个是不相同的,所以这两个对象会放在不同的索引之下。这样的话就会与hash的设计相冲突,导致整个 hash 结构无法正常工作。(父类的equals,子类的hashCode)
情况四:equals和hashCode都重写
我们通过重写的 equals 和 hashCode 判定得出,它们应该放在 hash 表的同一个索引之下,二者的表现一致,符合 hash 结构的设计理念。
问题解答
回到最开始的问题:
1、hashcode相等的两个对象一定==相等吗?equals相等吗?
2、两个对象用equals比较相等,那它们的hashcode相等吗?
由上面的探究可以得出:
两个对象==相等,则其hashcode一定相等,反之不一定成立。
两个对象equals相等,则其hashcode一定相等,反之不一定成立。
【注:hashCode 是由对象的内部地址经过 hash 函数得到的】
总结
本博客为个人的理解总结而来,如果有不对的地方,欢迎指出来,一起共同进步!!!
附
问题一:从源码角度解析 “==” 和 equals 关于引用数据类型方面的区别
参考链接:
1、hashcode相等的两个对象一定 == 相等么?equals相等么?
2、为什么重写equals必须重写hashCode