• 日常整理:为什么我们重写equals的时候也要重写hashcode


    如果我们使用了map等的容器,并且key采用的是自定义的对象,那这个是一定要重写的

    先说必要性,重写equals是为了判断实例是否相等,而重写hashcode是为了快速判重

    先看一下这几个比较重要的点

    - 如果两个对象相等,那么它们的 hashcode 一定相同

    - 如果两个对象相等,那么 equals() 方法返回的一定是true

    - 如果两个对象 hashcode 相同,它们本身并不一定相等

    所以,如果equals方法被重写了,hashcode也应该被重写

    hashcode本身的动作是在堆上的对象产生了一个独特的值,而如果没有重写hashcode,那么两个class对象无论如何都不会相等,就算这两个class对象指向了相同的数据

    我们来做个测试,只重写equals

    1. public static void main(String[] args) throws Exception {
    2. Info info = new Info("test");
    3. Info info1 = new Info("test");
    4. Map map = new HashMap<>(2);
    5. map.put(info, "对象1");
    6. map.put(info1, "对象2");
    7. System.out.println("map = " + map);
    8. }
    9. static class Info{
    10. private String message;
    11. public Info(String message) {
    12. this.message = message;
    13. }
    14. @Override
    15. public String toString() {
    16. return "Info{" +
    17. "message='" + message + '\'' +
    18. '}';
    19. }
    20. @Override
    21. public boolean equals(Object o) {
    22. if (this == o) return true;
    23. if (o == null || getClass() != o.getClass()) return false;
    24. Info info = (Info) o;
    25. return Objects.equals(message, info.message);
    26. }
    27. // @Override
    28. // public int hashCode() {
    29. // return Objects.hash(message);
    30. // }
    31. }

    可以看到结果

    我们再试试把hashcode的注释放开

    我们重写的equals的逻辑是,只要message相等,那么对象就相等,but,从map的运行结果看,都放进去了,so,我们来看看hashmap

    通过源码我们知道, hash不一样的话,可以直接插入到数组中,但是,因为我们没重写hashcode,所以调用了object的hashcode,而object的hashcode,是通过对象在堆里的地址计算出一个int值,所以,创建的不同对象的hashcode肯定是不同的,所以才会两个都插入到了map里

    -------------

    我们反一下,如果重写了hashcode,是不是要重写equals

    这个当然是的

    如果两个对象的hashcode相同,map在put的时候,hash相同,找到的位置就相同,取到了数据,进行equals比较,如果没有重写equals,那么就是对象地址在比较,结果就是false了,不信试试

     map在get的时候,是根据hashcode找,找到了,不止一个,那它就会用equals去找相等的值

    所以说,我们在使用中,如果重写了equals,也要重写hashcode

    如果你仔细观察,你会发现IDE其实也是放在一起的,比如我用IDEA

     总之,用的时候一定要小心哦

  • 相关阅读:
    6年测试开发经验面试28K公司后,整理出这套高频面试题和答案
    腾讯、飞书等在线表格自动化编辑--python
    利用 Forcing InnoDB Recovery 特性解决 MySQL 重启失败的问题
    一区W&R | 河海大学李轶课题组利用环境兼容的载氧生物炭修复缺氧淡水生物机制
    Qt QLabel文本框的使用
    STC15单片机-生产资料,项目结束
    2023年CNVD漏洞周报16期
    ubuntu20.04在docker下运行ros-noetic进行开发
    clickhouse在风控-风险洞察领域的探索与实践
    Redis6(一)——NoSQL数据库简介与Redis的安装
  • 原文地址:https://blog.csdn.net/weixin_46097842/article/details/126820366