为什么重写equals方法一定要重写hashcode
Posted 活跃的咸鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么重写equals方法一定要重写hashcode相关的知识,希望对你有一定的参考价值。
引言
在说明这个问题前我们先来看一下关于hashcode的一些硬性规定:
1.两个对象equals相等,hashcode一定相等。
2.两个对象equals不等,hashcode不一定不等。
3.两个对象的hashcode相等,两个对象不一定相等。
4.两个对象的hashcode不等,两个对象一定不等。
equals方法和hashcode方法介绍
equals方法和hashcode方法都是Object类里面的两个方法。
equals的作用是比较两个对象的地址值是否相等
hashcode方法的作用是返回该对象的十六进制的地址值。
他们的源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
验证结论
我们用几个例子来验证我们的程序是否遵循hashcode的硬性规定。
1.两个对象equals相等,hashcode一定相等。
public class Student {
public static void main(String[] args) {
Student student1= new Student("wf", "man");
Student student2 = new Student("wf", "man");
System.out.println(student1.equals(student2));
System.out.println(student1.hashCode()==student2.hashCode());
}
private String name;
private String sex;
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, sex);
}
}
true
true
2.两个对象equals不等,hashcode不一定不等也可能相等。
public class Student {
public static void main(String[] args) {
Student student1= new Student("wlf", "man");
Student student2 = new Student("wf", "man");
System.out.println(student1.equals(student2));
System.out.println(student1.hashCode()==student2.hashCode());
}
private String name;
private String sex;
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return 100;
}
}
false
true
3.两个对象的hashcode相等,两个对象不一定相等。
我们看1和2的结果知道hashcode都相等但是两个对象不一定相等。
4.两个对象的hashcode不等,两个对象一定不等。
public class Student {
public static void main(String[] args) {
Student student1= new Student("wlf", "man");
Student student2 = new Student("wf", "man");
System.out.println(student1.equals(student2));
System.out.println(student1.hashCode()==student2.hashCode());
}
private String name;
private String sex;
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, sex);
}
}
false
false
以上我们都是即重写equals又重写hashcode。
为什么重写equals方法一定要重写hashcode
现在有两个Student对象:
Student student1= new Student("wlf", "man");
Student student2 = new Student("wlf", "man");
此时s1.equals(s2)一定返回true
假如只重写equals而不重写hashcode,那么Student类的hashcode方法就是Object默认的hashcode方法,由于默认的hashcode方法是根据对象的内存地址经哈希算法得来的,显然此时s1!=s2,故两者的hashcode不一定相等。
然而重写了equals,且s1.equals(s2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从Student类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与Student的两个属性有关。
我们来看看重写后的hash算法
@Override
public int hashCode() {
return Objects.hash(name, sex);
}
Objects
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
Arrays
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result +
(element == null ? 0 : element.hashCode());
return result;
}
以上是关于为什么重写equals方法一定要重写hashcode的主要内容,如果未能解决你的问题,请参考以下文章
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?
关于object类的两个重要方法以及为什么重写equals一定要重写hashcode()
面试官:重写 equals 时为什么一定要重写 hashCode?