为什么如果重写了某个类的equals方法,还必须重写对应的hashcode方法?

为什么如果重写了某个类的equals方法,还必须重写对应的hashcode方法?

答:

  1. 保证equals相同的两个对象hashcode必须相同的原则。
  2. 不重写hashcode方法的的话,若用hashmap/hashset等散列表存储这个类,可能会出现两个相同对象hashcode却不同,导致判定为不同元素的问题。

第一个原因可以认为是一个大原则,第二个原因则可以认为是具体表现,下面具体解释第二个原因。

详细解释

比如hashmap插入时,会先判定新元素的hash值和旧元素的hash值是否相等,hash值相等前提下,再判断equals方法。如果不重写hashcode,则equal相等的两个元素,对应的hashcode可能会不同,就会导致本来两个相等的元素被判定为不同元素,重复插入。(所以一定要保证equals相同时,hashcode也相同,但反过来不用,因为允许冲突嘛)

实验验证

创建一个people对象,如果两个people对象的name以及age相同,就认为是相同的对象,要保证相同的people不能重复加入到hashset/hashmap中,如何实现?

做法一:定义people对象,只重写equals方法

java 复制代码
class people{
    String name;
    int age;

    public people(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "people{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        people people = (people) o;
        return age == people.age &&
                Objects.equals(name, people.name);
    }
}

测试代码

java 复制代码
public class HashSet_test1 {
    public static void main(String[] args) {
        HashSet s = new HashSet();
        s.add(new people("张三",20));
        s.add(new people("张三",20));
        s.add(new people("张三",21));
        System.out.println(s);
    }
}

测试结果,set里面插入了两个相同的对象,有问题

做法2:重写equals方法以及hashcode方法,保证name和age相同时,hashcode也相同

java 复制代码
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        people people = (people) o;
        return age == people.age &&
                Objects.equals(name, people.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);//使用Objects工具类提供的hash方法
    }

测试结果,set插入正常

结论:重写equals方法后,hashcode方法也必须对应重写

相关推荐
独泪了无痕3 小时前
探索Pinyin4j-Java中的拼音转换利器
java·后端
道尔柯南4 小时前
C++ string 类详解:从常用接口到深拷贝,彻底掌握字符串处理
android·java·c++
来让爷抱一个5 小时前
Python 异步里混用同步库,事件循环被卡住的全过程
开发语言·python
kingx35 小时前
Bugku 3122 谷歌小恐龙题解:纯离线逆向 Vault 的 AES-GCM 加密资源(附 Python 解密器)
java·逆向·ctf·bugku·aes-gcm
DevOpenClub7 小时前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
心祭丫丫8 小时前
【每天一个 Python 小案例17】Python 实现通讯录
开发语言·人工智能·笔记·python·学习
露天赏雪8 小时前
第3篇:Sentinel熔断降级实战:大模型接口抖动时的服务兜底方案
java·开发语言·人工智能·spring boot·spring·servlet·sentinel
天天被压力8 小时前
【A股分钟级高频数据完全手册 #06】北交所分钟级数据接口:京市股票Pro版最新分时
java·人工智能·python
天天被压力8 小时前
【A股分钟级高频数据完全手册 #05】指数历史分钟数据接口:Pro版沪深指数分时回放
java·人工智能·python
captain3768 小时前
▲统一功能——DispatcherServlet源码分析
java·spring·java-ee·log4j·maven