Why do I need to override the equals and hashCode methods in Java?
这个问题国内讨论出的答案各式各样,于是我去Stackoverflow中查看了一下这个问题的解
国外对于override the equals and hashCode的解释更多的是contract(合同,契约的意思),也就是说,重写equals必须重写hashcode已经达成了一种契约(或者说是定理?)
本篇文章来自于对该评论的解析
Why do I need to override the equals and hashCode methods in Java?
该作者是这样回答的:
像HashMap和HashSet是通过对象的hashcode来存储对象的,并且定位对象的时候也是通过hashcode
哈希检索是一个两步的过程。
-
找到正确的桶(使用hashCode())
-
在桶中搜索正确的元素(使用equals())
下面是一个小例子,说明为什么我们重写equals()的时候并且需要重写hashcode()
建立一个Employee类,它有两个变量age和name
public class Employee {
String name;
int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof Employee))
return false;
Employee employee = (Employee) obj;
return employee.getAge() == this.getAge()
&& employee.getName() == this.getName();
}
// 注释掉了
/* @Override
public int hashCode() {
int result=17;
result=31*result+age;
result=31*result+(name!=null ? name.hashCode():0);
return result;
}
*/
}
创建一个测试类ClientTest
public class ClientTest {
public static void main(String[] args) {
Employee employee = new Employee("rajeev", 24);
Employee employee1 = new Employee("rajeev", 25);
Employee employee2 = new Employee("rajeev", 24);
HashSet<Employee> employees = new HashSet<Employee>();
employees.add(employee);
System.out.println(employees.contains(employee2));
System.out.println("employee.hashCode(): " + employee.hashCode()
+ " employee2.hashCode():" + employee2.hashCode());
}
}
有注释的时候,他会打印出
false employee.hashCode(): 321755204 employee2.hashCode(): 375890482
现在我们取消注释hashcode(),他会打印出
true employee.hashCode(): -938387308 employee2.hashCode(): -938387308
第一个案例中,两个对象一模一样,但是hashcode不一样(即使equals()方法被重写,hashcode也还是不一样)
但是我们认为employee和employee2是一样的(如果我们添加100万个name="rajeev",age=24的对象,那么Hashset里面就会有100万个这样的"相同"的对象,这显然不是我们想要的)
如果传统的hashcode()方法不能反应这一点,那么我们就需要重写hashcode()方法.让两个对象是相等的,它们的哈希码也相等