为什么重写 equals 方法就必须重写 hashCode 方法?

简介: 为什么重写 equals 方法就必须重写 hashCode 方法?

简答版

       因为我们在使用 HashMap 或 HashSet 集合类的时候,需要用到哈希表,哈希表必须满足 两个对象 equals 返回 true时,两个对象 hashCode 返回的哈希值必须相同,而我们重写equals方法后,可能导致两个对象 equals 返回 true ,而 hashCode 返回的哈希值不相同,导致哈希表中存储了两个相同的对象

详答版

我们知道

  • 当两个对象 equals 返回 true 时,则两个对象就是相同的
  • 哈希表中不能存储两个相同的元素

哈希表 的原理是

  • 先比较两个对象的哈希值,如果哈希值不同,则这两个对象不可能相同,无需调用 equals 方法进行比较
  • 如果哈希值相同,这两个对象不一定相等,因此会再使用 equals 方法进行比较,来确定这两个对象是否相等
  • 并且哈希表中不能存储两个相同的元素

因此 equals 方法 和 hashCode方法必须满足

  • hashCode相同时,equals 方法不一定返回 true
  • equals 方法返回 true 时,两个对象 hashCode 返回的哈希值必须相同

而如果重写了 equals 方法,而没有重写 hashCode 方法,就有可能导致 equals 返回true,而hashCode 返回的哈希值不相同

那么哈希表在存储数据的时候,比较到两个对象的哈希值不相同,就认为两个对象不同,不在调用equals方法,将两个对象都存储在哈希表中,这就导致了哈希表的错误

我们看下面的一个例子

import java.util.Objects;
public class Student {
    String name;
    int age;
    public Student(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;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }
}

上面的Student类我们重写了equals方法,但没有重写hashCode方法,然后进行测试

public class Test {
    public static void main(String[] args) {
        Student student01=new Student("张三",18);
        Student student02=new Student("张三",18);
        System.out.println(student01.equals(student02));
        Set<Student> studentSet = new HashSet<>();
        studentSet.add(student01);
        studentSet.add(student02);
        System.out.println(studentSet);
    }
}

8bdc2a4587e54eae870598d02aebfb83.png

我们看到 HashSet 是 不可重复 的集合,却存入了两个相同的对象

现在我们重写hashCode方法

import java.util.Objects;
public class Student {
    String name;
    int age;
    public Student(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;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

在进行相同的测试

我们看到了这次就存储进一个对象

结论

重写equals方法的时候一定要重写hashCode方法

我们在自定义类的时候,equals方法默认使用 == 比较对象地址,而我们一般会重写以比较对象属性,而在idea中,当我们重写equals方法的时候,会自动帮我们重写hashCode方法

目录
相关文章
|
7月前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
59 0
|
2月前
|
存储 算法 Java
为什么重写 equals 方法时必须同时重写 hashCode 方法?
本文探讨了 Java 中 `hashCode` 方法的作用及其与 `equals` 方法的关系,解释了为什么重写 `equals` 方法时必须同时重写 `hashCode` 方法,并提供了如何正确重写 `hashCode` 方法的示例。
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
69 0
|
7月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
7月前
|
存储 IDE Java
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
50 1
|
存储 Java
重写equals方法
我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
85 0
|
Oracle Java 关系型数据库
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap
首先我们有一个假设:任何两个 object 的 hashCode 都是不同的。 那么在这个条件下,有两个 object 是相等的,那如果不重写 hashCode(),算出来的哈希值都不一样,就会去到不同的 buckets 了,就迷失在茫茫人海中了,再也无法相认,就和 equals() 条件矛盾了,证毕。
152 0
为什么重写 equals() 方法,一定要重写 hashCode() 呢?| HashMap
|
存储 算法 Java
(强制)要求覆写equals必须覆写hashCode(原理分析)
hashCode和equals hashCode和equals用来标识对象,两个方法协同工作可用来判断两个对象是否相等。众所周知,根据生成的哈希将数据散列开来,可以使存取元素更快。对象通过调用Object.hashCode()生成哈希值;由于不可避免会存在哈希值冲突 的情况,因此当hashCode相同时,还需要再调用equals进行一次值的比较;但是若hashCode不同,将直接判定Object不同,跳过equals,这加快了冲突处理效率。Object类定义中对hashCode和equals要求如下:
244 0
|
存储 算法 Java
面试题系列第4篇:重写了equals方法,为什么还要重写hashCode方法?
面试题系列第4篇:重写了equals方法,为什么还要重写hashCode方法?
161 0
面试题系列第4篇:重写了equals方法,为什么还要重写hashCode方法?