请选择 进入手机版 | 继续访问电脑版

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 78|回复: 0

[Java] 为什么一个对象重写了equals必须也重写hashCode

[复制链接]

4306

主题

0

回帖

4306

积分

论坛元老

积分
4306
威望
0
金币
9168
贡献
0
注册时间
2022-7-17
最后登录
2022-8-27
发表于 2023-4-2 20:16:00 | 显示全部楼层 |阅读模式

人人为我,我为人人。登录后免费下载所有资源。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一言以蔽之:重写
  1. equals
复制代码
方法是为了比较对象的内容是否相等,重写
  1. hashCode
复制代码
方法是为了保证对象在哈希表等数据结构中的正确性。

1、在 Java 中,如果一个类重写了
  1. equals
复制代码
方法,则必须同时重写
  1. hashCode
复制代码
方法。这是因为在 Java 中,对象的
  1. hashCode
复制代码
值用于在哈希表(Hash Table)等数据结构中进行快速查找,而哈希表的实现原理是根据对象的
  1. hashCode
复制代码
值进行散列(Hash),所以如果两个对象的
  1. equals
复制代码
方法返回
  1. true
复制代码
,则它们的
  1. hashCode
复制代码
值也必须相等,否则可能会导致哈希表的查询等操作出现错误结果。
以下是一个示例,演示了为什么需要同时重写
  1. equals
复制代码
  1. hashCode
复制代码
方法:
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 obj) {
        if (this == obj) return true;
        if (!(obj instanceof Person)) return false;
        Person person = (Person) obj;
        if (age != person.age) return false;
        if (name != null ? !name.equals(person.name) : person.name != null) return false;
        return true;
    }
}
如果只重写了
  1. equals
复制代码
方法,而没有重写
  1. hashCode
复制代码
方法,则可能会导致哈希表中出现错误的结果:
Person p1 = new Person("Alice", 18);
Person p2 = new Person("Alice", 18);
MapPerson, String map = new HashMap();
map.put(p1, "Hello");
// 此时尝试获取 p2 对应的值,由于没有重写 hashCode 方法,p1 和 p2 的 hashCode 值不相等
// 因此,虽然 p1 和 p2 的 equals 方法返回 true,但是从哈希表中获取 p2 对应的值时却会失败
String value = map.get(p2); // value 为 null
2、下面是一个重写了
  1. hashCode
复制代码
方法的示例代码:
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 obj) {
        if (this == obj) return true;
        if (!(obj instanceof Person)) return false;
        Person person = (Person) obj;
        if (age != person.age) return false;
        if (name != null ? !name.equals(person.name) : person.name != null) return false;
        return true;
    }
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}
在上面的示例代码中,
  1. hashCode
复制代码
方法重写的实现逻辑与
  1. equals
复制代码
方法的实现逻辑是一致的,都是比较
  1. Person
复制代码
对象的两个属性
  1. name
复制代码
  1. age
复制代码
是否相等,如果相等则返回相同的
  1. hashCode
复制代码
值。
需要注意的是,这里的
  1. 31
复制代码
是一个质数,它的作用是为了避免哈希冲突,因为
  1. 31
复制代码
的乘法运算比较快,而且相对来说能够更加均匀地散布哈希值,从而减少哈希冲突的发生。
重写了
  1. hashCode
复制代码
方法之后,就可以保证在哈希表等数据结构中,同一个对象的
  1. hashCode
复制代码
值不变,不同对象的
  1. hashCode
复制代码
值不同,从而能够正确地进行查找和比较操作。
我爱编程论坛www.woaibiancheng.cn
回复

使用道具 举报

侵权举报|手机版|我爱编程论坛 ( 蜀ICP备2022018035号-1 )

GMT+8, 2023-10-3 23:08

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表