在Java中,重写equals()方法的同时也应该重写hashCode()方法,这是因为这两个方法在 Java 中是有关联的,而且它们一起影响着集合类的行为。
Java中的hashCode()方法用于返回对象的哈希码,而equals()方法用于比较两个对象是否相等。在集合类(如HashMap、HashSet等)中,hashCode()方法被用来确定对象在内部存储结构中的位置,以便更快地进行查找。如果两个对象在equals()方法中被认为相等,那么它们的hashCode()方法应该返回相同的值。
下面是一些原因说明为什么重写hashCode()方法是很重要的:
集合类的性能: 在使用哈希集合(如HashMap、HashSet)时,对象的hashCode()方法影响着集合的性能。如果两个相等的对象返回不同的哈希码,它们可能会被放置在不同的存储桶中,导致集合无法正确工作。
保持一致性: 根据equals()方法的规范,如果两个对象相等,它们的哈希码应该相等。这是为了确保当一个对象被修改后,它在集合中的位置不会改变,从而保持集合的一致性。
符合对象相等性原则: 如果两个对象通过equals()方法比较相等,那么它们的哈希码应该相等。这是为了保持Java对象相等性原则的一致性。
为了满足这些要求,当你重写了equals()方法时,最好也一并重写hashCode()方法。
当你只重写了equals()方法而没有重写hashCode()方法时,可能导致相等的对象拥有不同的哈希码,这会违反哈希表的基本性质。下面是一个例子:
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
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 o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
// @Override
// public int hashCode() {
// return Objects.hash(name, age);
// }
}
public class myTest {
public static void main(String[] args) {
Map<Person, String> personMap = new HashMap<>();
Person person1 = new Person("John", 25);
Person person2 = new Person("John", 25);
System.out.println(person1 == person2); // new出来的两个对象,内存地址肯定不一样,所以返回false
System.out.println(person1.equals(person2)); // true return age == person.age && Objects.equals(name, person.name);
personMap.put(person1, "Person 1"); // 向map集合中添加数据
// 尽管 person2 与 person1 equals() 返回 true,但由于没有重写 hashCode(),它们的哈希码不同
// 取值
System.out.println(personMap.get(person2)); // 输出 null
System.out.println(personMap.get(person1)); // 输出 Person 1
}
}
结果1:
没有重写hashcode()方法
personMap.get(person2)时,返回的结果为null。这违反了哈希表的期望行为,即相等的对象应该有相等的哈希码。
结果2:
同时重写equals() 和 hashcode() 方法
此时用personMap.get(person2)取值时,结果返回Person 1
这确保了相等的对象具有相等的哈希码。在实际应用中,你可能需要根据具体的对象属性选择更适合的生成哈希码的方式。