为什么要重写hashCode和equals方法


前言

在idea编译器中重写equals方法和重写hashCode方法捆绑在一起,同时在学习到set集合时也常看到各种资料写着hashCode和equals方法都需要重写,这是为什么呢?
以下是我的个人理解


一、什么是hashCode?

hashCode是Object类中定义的一个方法,则任何类都继承自Object方法,常见的Integer类,String类在查看源码时发现都有重写过hashCode,而自定义类继承自Object父类的hashCode方法,Object类的hashCode方法是根据内存地址计算返回的,此时需要联系数据结构的哈希表进行联想,假设把他当做哈希表的链地址表示法的数组下标进行简化。

二、向HashSet添加数据流程

(1)当往HashSet添加数据时候,需要先调用hashCode方法计算出元素的哈希值
(2)将计算出的哈希值对一个数取余(此处为了方便设数组长度为16)
(3)在找到相应的节点下表后,看这个节点是否包含数据,里面没有数据将其存在这里并设为链表的头结点
(4)如果存储节点有数据了,会和当前节点下的数据的哈希值挨个比较,如果哈希值不同则数据一定不同,可作为链表节点直接插入
(5)如果保存元素和已有元素的哈希值相同,并不能判断数据一定相同,还需要进行equals()比较,如果返回false,则不认为数据重复;否则,认为数据重复

三、不重写hashCode但重写了equals怎么样

在这里插入图片描述

以上例子可以看出不同元素没重写hashCode时出现的哈希碰撞和相同对象但返回哈希值不同的情况

在这里插入图片描述

上图中假设每个狗都是一个对象,狗一的哈希值对16取余放在数组下标为5的位置;狗二、狗三、狗四对16取余都为8,其中狗二和狗三是两个完全相同的元素,但因为没有重写hashCode导致哈希值并不相同,根据向HashSet放入步骤可以看出,放狗二时发现8号下标为空,可以直接放入;狗三时发现该下标已有元素,但是hashCode并不相同,可直接链在狗二的下面;狗四时发现hashCode值相同,但equals比较后不同,可直接链在下边。
此时HashSet中存在相同元素狗二和狗三,并不符合hashSet没有重复元素。

四、重写了hashCode和equals比较逻辑

在这里插入图片描述

此例子中在放狗一时将哈希值对16取余,放在标号为3的位置;狗二对16取余时发现结果为3,该位置有元素,比较哈希值发现并不相同,可以直接链在下面;狗三取余时发现结果也为3,比较哈希值发现相等,此时可能是哈希碰撞还需比较equals方法,equals比较后发现是同一元素,则不用存储;狗四对16取余放在0号下表位置。
此时HashSet已完成去重操作。

总结

当没重写hashCode时,自定义类会调用父类Object的hashCode方法,父类hashCode方法是根据地址值进行运算的,重写hashCode方法后会按照内容计算得出哈希值;自定义类new出来两个对象,即使元素内容完全相同,但是地址不同计算出得哈希值不同,哈希值不同就可认为元素不同,直接加入到哈希表中,没有实现去重操作;但重写hashCode后会根据元素内容重新生成一个哈希值,不在根据地址值来进行判断,相同哈希值的元素必然会定位到同一下标位置,此时需要equals方法进行比较,在没有重写equals方法时调用的时Object类的equals方法,父类equals方法仅仅是==判断比较的是地址值,需要自己重写来判断内容,当且仅当哈希值相同且元素内容完全相同时才会进行去重,若哈希值相同但元素内容不同时仍会正常加入哈希表中。
(重写hashCode和equals方法后:哈希值不同则元素一定不同,hashCode相同equals不一定相同,equals相同hashCode一定相同)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值