在 Java 中,当一个类重写了 equals
方法时,通常也需要重写 hashCode
方法。这是因为在使用哈希集合(如 HashSet
、HashMap
等)时,hashCode
方法的作用非常重要。
哈希集合通过哈希值(即 hashCode
方法返回的值)来确定元素在集合中的位置。当我们向哈希集合中添加元素时,集合会首先计算元素的哈希值,然后根据哈希值找到元素在集合中的位置。如果两个对象在 equals
方法中被认为是相等的,则它们必须具有相同的哈希值,以确保它们能够被正确地处理。
如果重写了 equals
方法但没有重写 hashCode
方法,那么可能会导致以下问题:
- 相等的对象具有不同的哈希值,这将违反哈希集合的约定,导致无法正确地查找和删除对象。
- 相等的对象可能被错误地视为不同的对象,因为它们的哈希值不同。
下面是一个简单的示例,展示了在重写 equals
方法时为什么也需要重写 hashCode
方法:
import java.util.HashMap;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age &&
name.equals(person.name);
}
// 没有重写 hashCode 方法
public static void main(String[] args) {
HashMap<Person, String> map = new HashMap<>();
Person person1 = new Person("Alice", 30);
Person person2 = new Person("Alice", 30);
map.put(person1, "Person 1");
map.put(person2, "Person 2");
System.out.println(map.size()); // 输出:2,因为没有重写 hashCode 方法,导致两个相等的对象具有不同的哈希值,被认为是不同的对象
}
}
在这个例子中,Person
类重写了 equals
方法来比较两个 Person
对象是否相等。然而,由于没有重写 hashCode
方法,导致两个相等的 Person
对象具有不同的哈希值,因此被哈希集合(HashMap
)视为不同的对象,最终导致集合中包含了两个相等的对象。
要重写 hashCode
方法,可以根据 equals
方法中使用的字段来生成哈希值。通常情况下,可以将对象中每个用于比较相等性的字段的哈希值合并起来生成一个新的哈希值。以下是一个修复上面示例的方式:
import java.util.HashMap;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age &&
name.equals(person.name);
}
@Override
public int hashCode() {
return name.hashCode() + age; // 将 name 的哈希值和 age 相加
}
public static void main(String[] args) {
HashMap<Person, String> map = new HashMap<>();
Person person1 = new Person("Alice", 30);
Person person2 = new Person("Alice", 30);
map.put(person1, "Person 1");
map.put(person2, "Person 2");
System.out.println(map.size()); // 输出:1,重写了 hashCode 方法后,两个相等的对象具有相同的哈希值,被视为同一个对象
}
}
在这个例子中,hashCode
方法使用了 name.hashCode()
和 age
的值的相加来生成哈希值。这样,两个相等的 Person
对象将具有相同的哈希值,因此被哈希集合视为同一个对象。