当前位置: 首页 > news >正文

为什么重写equals方法必须也要重写hashCode方法

目录

一、了解equals方法与hashCode方法

1、equals方法

2、hashCode方法

hashCode方法

hash值

3、分析

二、分析

1、equals在观感上的问题

2、只重写equals带来的问题

三、总结


一、了解equals方法与hashCode方法

1、equals方法

java顶级父类Object的equals方法源码

    public boolean equals(Object obj) {
        return (this == obj);
    }

可以看出equals方法底层通过”==“判断是否相等,即判断两个对象的地址是否相同

2、hashCode方法

hashCode方法

hashcode方法通过特定的算法,将对象的内存地址等所有信息映射为一个数组,即散列值

hash值

系统通过特定的算法,将散列值映射为一个定长的值,即hash值(哈希值)

hash值主要是用来在散列存储结构中确定对象的存储地址的,提高对象的查询效率

3、分析

如果两个对象通过equals判断相等,那么它们的地址和内容都一定相等,因此算出来的hashCode和hash值也一定相等

如果两个对象通过equals判断不相等,那么它们的地址一定不同,但是内容可能相等,算出来的hashCode和hash值有可能相等


二、分析

1、equals在观感上的问题

使用原生equals是通过两个对象的地址判断是否相等,这会导致一个问题,两个对象拥有完全相同的内容,但是equals判断不相等

    private String name;
    private Integer age;

    public test0830(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
        test0830 t1 = new test0830("张三",20);
        test0830 t2 = new test0830("张三",20);
        System.out.println(t1.equals(t2));

 

 在人的主观感受上,内容相同的两个对象是应该相等的,即使他们地址不同

因此可以重写equals方法,重写后只要内容完全相同,那么就返回true。但这会带来新的问题。

    @Override
    public boolean equals(Object obj){
        if (this == obj){
            return true;
        }
        if (obj == null || getClass() != obj.getClass()){
            return false;
        }
        test0830 temp = (test0830)obj;
        return this.name == temp.name && this.age ==temp.age;
    }

  

2、只重写equals带来的问题

在重写equals方法后,上面t1和t2两个对象经过判断是相等的

但是这两个对象的地址不同,他们的hash值也不同,当把这两个对象放进HashSet中,会有两个值,而不是去重后只有一个值

        HashSet<test0830> set = new HashSet<>();
        set.add(t1);
        set.add(t2);
        System.out.println(set.size());

 

为了解决这种问题,需要重写hashCode方法,让hashCode根据name和age来映射散列表,不再管内存地址

    @Override
    public int hashCode(){
        return Objects.hash(name,age);
    }

 

 这下HashSet实现了去重,问题解决


三、总结

根据人对”相等“的主观认识而重写的equals方法,如果不再根据对象的地址判断是否相等,HashSet就会出现不能去重的问题。因为此时hashCode方法仍然根据对象的内存地址生成不同的散列值,最终确定对象地址的hash值也会不同,影响HashSet中数据的存储。

HashSet

  • 用于存放对象
  • HashSet 是一个没有重复元素的集合。
  • 基于HashMap实现

HashMap

  • 存放键值对,key-value
  • key不可重复,value可重复
  • 底层基于数组+链表+红黑树实现,红黑树需要jdk≥1.8。数组的每一项都是个单链表,每个键值对根据key的hash算法确定数组中的存放位置,再根据equals判断在链表上的位置。只重写equals,会造成equals判断为true的多个对象hash值不同,而存储在不同位置,相当于不重复,出现程序逻辑错误

相关文章:

  • 只要十分钟!带你了解Redis Cluster
  • CREO:CREO软件之零件【造型】样式栏之操作、平面、曲线、曲面、分析、优先选项的简介及其使用方法(图文教程)之详细攻略
  • app毕业设计开题报告基于Uniapp实现的美食餐厅订单点餐APP
  • 基于51单片机十字路口交通灯_5s黄灯闪烁
  • Java并发 | 13.[设计模式] 两阶段终止线程
  • 一次服务器被入侵的处理过程分享
  • Java并发 | 11.[方法] join( )和join( long m )等待线程执行完毕
  • es重启临时关闭自动分片
  • Git仓库4(分支操作冲突,标签管理)
  • camera特效app(安卓)
  • JAVA代码 企业人力资源管理系统(详细带截图) 毕业设计
  • Spring 事务
  • 海滩的海鸥
  • 医疗系统业务流程
  • 云计算-虚拟化
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • hexo+github搭建个人博客
  • SegmentFault for Android 3.0 发布
  • Android框架之Volley
  • E-HPC支持多队列管理和自动伸缩
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java Agent 学习笔记
  • JavaScript DOM 10 - 滚动
  • Javascript弹出层-初探
  • JS专题之继承
  • MD5加密原理解析及OC版原理实现
  • Spark学习笔记之相关记录
  • 爱情 北京女病人
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 解析带emoji和链接的聊天系统消息
  • 聊聊flink的TableFactory
  • 你不可错过的前端面试题(一)
  • 世界上最简单的无等待算法(getAndIncrement)
  • 跳前端坑前,先看看这个!!
  • 温故知新之javascript面向对象
  • 一些css基础学习笔记
  • PostgreSQL之连接数修改
  • ###C语言程序设计-----C语言学习(6)#
  • #《AI中文版》V3 第 1 章 概述
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (9)目标检测_SSD的原理
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (第一天)包装对象、作用域、创建对象
  • (二)丶RabbitMQ的六大核心
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (一)基于IDEA的JAVA基础12
  • (转)Linux下编译安装log4cxx
  • (转)scrum常见工具列表
  • (转载)Google Chrome调试JS
  • .apk 成为历史!
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .Net Redis的秒杀Dome和异步执行
  • .NET成年了,然后呢?
  • .net打印*三角形