在 Java 中,equals()和 hashCode()方法需要同时重写的原因有以下几个:
1. 确保对象比较的一致性
当重写 equals()方法时,您定义了比较两个对象相等性的规则。如果只重写 equals()方法,但未重写 hashCode()方法,那么 Java 默认使用对象的内存地址作为哈希码。这可能会导致不一致的比较结果,因为两个具有相同 equals()结果的对象可能具有不同的哈希码。
2. 优化集合和映射的性能
Java 集合和映射使用哈希表来存储对象。哈希表依赖于对象的哈希码来确定对象的存储位置。如果只重写 equals()方法,但未重写 hashCode()方法,那么具有相同 equals()结果的对象可能存储在哈希表中的不同位置。这会降低集合和映射的性能,因为查找对象需要检查多个哈希表桶。
3. 遵守 Java 标准库的约定
Java 标准库中的类的大多数实现都遵循一个约定,即如果两个对象相等,那么它们的哈希码也相同。如果只重写 equals()方法,但未重写 hashCode()方法,那么您的类将违反此约定。
举例说明
假设有一个Person类,其中有两个属性name和age,我们重写equals()方法来判断两个Person对象是否相等:
public 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 instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
// hashCode() method not overridden!
}
如果我们创建两个相同内容的Person对象并尝试将它们插入到HashSet中,我们期望集合中只有一个元素,因为他们逻辑上是"相等"的。但如果我们没有重写hashCode()方法,就会发生以下情况:
HashSet<Person> people = new HashSet<>();people.add(new Person("John", 30));people.add(new Person("John", 30));System.out.println(people.size()); // 这会输出2而不是预期的1
由于hashCode()方法未被重写,每个Person对象都会有一个基于其内存地址不同的默认哈希码,所以即使equals()方法表明这两个对象是相等的,HashSet仍会把它们视为不同的元素加入到集合中。
要解决这个问题,我们应该根据同样的属性重写hashCode()方法:
public int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
当equals()和hashCode()都基于name和age这两个字段时,符合约定,可以确保集合行为正确。现在,HashSet将只保存一个Person元素,因为两个Person实例虽然是不同的对象,但它们是"相等"的,并且具有相同的哈希码。
总结:重写这两个方法的关键在于维护对象的一致性,使其在集合中表现得符合预期。否则,会导致数据结构中的元素查找、插入、删除等操作出现异常行为。
本篇文章来源于微信公众号: 互联网面试小帮手
微信扫描下方的二维码阅读本文

Comments NOTHING