为什么重写 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() 方法,以维护良好的编程实践。

相关文章
|
30天前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
22 0
|
4月前
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
44 0
|
1月前
|
自然语言处理 算法 Java
为什么说重写equals时要重写hashcode
为什么说重写equals时要重写hashcode
|
1月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
8月前
|
存储
为什么重写 equals 方法就必须重写 hashCode 方法?
为什么重写 equals 方法就必须重写 hashCode 方法?
60 0
|
9月前
|
存储 Java
重写equals方法
我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系
|
9月前
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
55 0
|
存储 算法 Java
(强制)要求覆写equals必须覆写hashCode(原理分析)
hashCode和equals hashCode和equals用来标识对象,两个方法协同工作可用来判断两个对象是否相等。众所周知,根据生成的哈希将数据散列开来,可以使存取元素更快。对象通过调用Object.hashCode()生成哈希值;由于不可避免会存在哈希值冲突 的情况,因此当hashCode相同时,还需要再调用equals进行一次值的比较;但是若hashCode不同,将直接判定Object不同,跳过equals,这加快了冲突处理效率。Object类定义中对hashCode和equals要求如下:
192 0
|
Oracle Java 关系型数据库
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap
首先我们有一个假设:任何两个 object 的 hashCode 都是不同的。 那么在这个条件下,有两个 object 是相等的,那如果不重写 hashCode(),算出来的哈希值都不一样,就会去到不同的 buckets 了,就迷失在茫茫人海中了,再也无法相认,就和 equals() 条件矛盾了,证毕。
119 0
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap
|
存储 算法 搜索推荐
面试题:重写equals方法为什么通常会重写hashcode方法?
面试题:重写equals方法为什么通常会重写hashcode方法?
139 0