为什么重写equals时最好同时重写hashCode方法?

为什么重写equals时最好同时重写hashCode方法?

想弄清楚这个问题,首先需要知道一点前置知识

  • equals是Object超类中的方法,默认是比较调用对象和参数对象内存地址是否相等,在没重写该方法时,它的作用就是如此(如果被重写,那么大部分情况下都是比较属性值是否相等
  • hashCode方法也是Object超类中的方法,它的作用是返回对象的hash值,这种hash值在没有被重写方法的情况下默认是通过对象的内存地址实现的(如果被重写,那么hashCode则根据对象的属性去获得而不是地址),大部分情况下针对不同对象可以正确返回不同hash值,但是也有可能出现相同的值(小概率)。就像我定义了一个取余数的算法%3,使用4和7对3取余数都等于1,那么就出现碰撞了,所以通过这些知识我们可以得出一个结论:在没重写该方法时,内存地址相等的对象的hashCode一定相同,但是相同hashCode的对象不一定相等

我们自定义对象时,一般都会重写equals方法和hashCode方法,原因在这里

因为业务中可能会涉及到Map,Set等数据结构,假设我创建了一个Person对象,拥有name和age属性
我创建两个对象p1和p2,属性都给name=小米,age=6,那么我将这两个对象put到Map中,此时Map将有几个值?
在这里插入图片描述
可以看到,即使我们认为这两个对象内容相同,Map应该只有一个,可是两个内容相同的key还是存在了两个,这是为啥呢?

  • 第一,此时我们只是认为p1和p2相等而已,实际上拿equals一比较就发现返回的是false了,因为没有重写equals,默认是拿p1的地址=p2的地址比较的。
  • 第二,即使我们重写了equals方法,比较内容相等是可以返回true了,但是实际上对于上图的代码来说是没有任何变化的,Map还是会存两个相同的小米对象,因为Map的K,在存入时首先判断的是对象的hashCode,但是我们只是重写了equals,并没有重写hashCode,所以才会导致两个表面上相等的对象在Map看来其实是不同的东西。(这也是Java推荐在重写equals时最好同步重写hashCode的原因)
  • 第三,如果想做到将p1,p2存入Map时,Map只存储最后一个,那就需要在Person对象中重写hashCode方法,这样就不会出现Map、Set等集合存入重复对象的问题了。Map将会在hashCode相等的对象上再进行equals比较,当两个都为真时,才确定是一样的对象,则不会重复存储,而是会覆盖。

结论

  • 对于自定义的对象来说,如果只是重写equals而未重写hashCode,那么可能会在Set集合、Map等结构中出现对象属性相同但是重复存储的情况(因为它们优先比较hashCode,而你没重写,那么就以内存地址计算hashCode)
  • 对于自定义的对象来说,如果只是重写hashCode而未重写equals,那么同一个对象现在确实可以根据属性内容返回正确的hashCode了,但是由于没有重写equals方法,当Set集合、Map等结构中存储元素时发现hashCode相同,那么再调用equals方法一判断!发现结果又是false了,那么它们认为这还是不同的对象(仅仅只是hash碰撞而已),结果又出现对象属性相同但是重复存储的情况
  • 所以不管在重写equals还是hashCode时,最好都把另一个方法重写,它们是一对!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值