为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)

简介: 为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)

Object 的 equals() 默认比较的是对象的内存地址

hashCode() 也是对对象的内存地址进行hash。

所以在涉及到hashcode的容器中(比如HashSet),判断自己是否持有该对象时,会先检查hashCode是否相等,如果hashCode不相等,就会直接认为不相等,并存入容器中,不会再调用equals进行比较。

但是hashCode()会出现哈希冲突,当发现哈希冲突时,便需要equals方法进行判断两者是否相等

如果重写了equals方法,相等的元素内存地址不一定相等。若不重写hashcode,还是可能会发生元素相同问题。所以要重写hashCode()。因此要重写hashCode保证:如果equals判断是相等的,那hashCode值也要相等。

哈希冲突:不同数值却拥有相同哈希值。

在Java中,equals() 方法用于比较对象的内容是否相等,而 hashCode() 方法用于获取对象的哈希码。这两个方法在某些场景下是紧密关联的,尤其是在使用哈希集合(如 HashMapHashSet)时。在这篇博客中,我们将深入探讨为什么在重写 equals() 方法的同时必须重写 hashCode() 方法。

相等对象应该有相等的哈希码

在Java中,如果两个对象通过 equals() 方法判断相等,那么它们的哈希码应该相等。反之亦然,即如果两个对象的哈希码相等,它们不一定通过 equals() 方法判断相等。

为什么要保持这种关系呢?原因在于哈希集合的实现,比如 HashMap。这些集合通过哈希码来确定对象在内部数据结构中的存储位置。当我们尝试查找某个对象时,先根据哈希码定位到可能的存储位置,然后再通过 equals() 方法来确保找到的是真正相等的对象。

如果两个相等的对象具有不同的哈希码,那么它们将被存储在不同的位置,导致无法正确地通过 equals() 方法找到这些对象。

重写 equals() 的常见场景

1.类表示值: 如果一个类的实例是不可变的,并且表示值(如字符串、数字),那么通常需要重写 equals() 方法。

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    MyClass myObject = (MyClass) obj;
    return Objects.equals(value, myObject.value);
}

2. 自定义类: 自定义类需要比较对象的内容时,也需要重写 equals() 方法。

@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 && Objects.equals(name, person.name);
}

为什么必须重写 hashCode()

在Java中,hashCode() 方法返回对象的哈希码,它在哈希集合中起着关键的作用。当我们将对象放入哈希集合时,集合通过对象的哈希码来决定对象的存储位置。

如果我们在重写了 equals() 方法的同时不重写 hashCode() 方法,可能导致以下问题:

  1. 相等对象哈希码不同: 如果两个对象通过 equals() 判断相等,但它们的哈希码不同,这将违反哈希集合的原则,导致无法正确处理相等对象。
  2. 相同哈希码不等对象: 如果两个对象的哈希码相等,但它们通过 equals() 判断不相等,这可能导致哈希集合中存储重复的对象,破坏集合的正确性。

因此,为了确保哈希集合正常运作,必须同时重写 equals()hashCode() 方法。这可以通过IDE(如Eclipse、IntelliJ IDEA)提供的工具来自动生成。

重写 hashCode() 的实例

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

 

这个例子中,使用 Objects.hash() 方法来组合多个属性的哈希码,以确保生成的哈希码是基于所有相关属性的。这有助于避免相等对象的哈希码不同的问题。

总结

在Java中,equals()hashCode() 方法的正确实现对于正确使用集合类非常重要。通过保持相等对象具有相等的哈希码,我们可以确保哈希集合的正确性,防止发生数据结构中的问题。因此,在重写 equals() 方法时,务必同时重写 hashCode() 方法,以维护良好的编程实践。

相关文章
|
6月前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
54 0
|
24天前
|
存储 算法 Java
为什么重写 equals 方法时必须同时重写 hashCode 方法?
本文探讨了 Java 中 `hashCode` 方法的作用及其与 `equals` 方法的关系,解释了为什么重写 `equals` 方法时必须同时重写 `hashCode` 方法,并提供了如何正确重写 `hashCode` 方法的示例。
|
11月前
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
66 0
|
6月前
|
自然语言处理 算法 Java
为什么说重写equals时要重写hashcode
为什么说重写equals时要重写hashcode
|
6月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
存储
为什么重写 equals 方法就必须重写 hashCode 方法?
为什么重写 equals 方法就必须重写 hashCode 方法?
76 0
|
存储 Java
重写equals方法
我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
81 0
|
存储 Java 对象存储
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?
|
Oracle Java 关系型数据库
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap
首先我们有一个假设:任何两个 object 的 hashCode 都是不同的。 那么在这个条件下,有两个 object 是相等的,那如果不重写 hashCode(),算出来的哈希值都不一样,就会去到不同的 buckets 了,就迷失在茫茫人海中了,再也无法相认,就和 equals() 条件矛盾了,证毕。
150 0
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap