为什么hashcode方法和equals方法要同时重写

首先我们需要明确这个问题,是因为hashmap或者hashset我们需要往里面put元素的时候,不能有两个完全的相同的值进入容器内部,否则,我们需要从集合中取出元素或者删除元素的的时候,就可能会导致重复的元素重复取出。
所以在往集合中存入元素的时候,就会涉及到两个操作,检查当前需要存入元素的key值的hashcode是否在集合中存在,如果存在,则再进行对equals的比较,如果equals为false,则存入。如果hashcode不存在,则直接放入集合(这里这样设计的原因是因为equals的性能开销比较大,也是为了防止不同元素存在hash冲突的时候无法存入集合的情况产生)。
第二,我们需要知道重写两个方法的前后都分别做了什么

  • hashcode(重写前):jvm通过对象的内存地址值,为对象分配一个随机数。
  • hashcode(重写后):通过对象的内容值,分配一个随机数
  • equals(重写前):比对两个对象的内存地址值,如果两个引用指向同一个对象,则才会返回true,否则返回false
  • equals(重写后):比对两个对象的内容值,如果内容完全相同,则返回true,否则返回false
    根据上面的描述,我们可以分出两种情况讨论
  1. 当重写hashcode,而不去重写equals方法的时候:
    首先我们拿到需要存放的元素的key值,调用它自身的hashcode方法,此时hashcode已经重写,返回的是根据他内容值获取的一个随机数,一般情况下,如果hashcode与集合中的元素的key值的hashcode重复,有两种情况,第一,是真的需要存入的元素和集合中的元素值相等,例如需要存入person.name=“小明”,而恰好,集合中已经有个元素的key为person.name=“小明”,他们俩是重复的,不再去存放,但是可能有第二种可能,我们在代码中hashcode是随机给到的一个数值,两个完全不相同的元素是完全有可能产生相同值的,尽管这个概率或许特别小,这种情况,我们称之为哈希碰撞,为了使得元素正确的存放进集合,此时,会调用到没有重写的equals方法对两个元素进行内存地址值的比较,如果此时我放入两个内容值完全相同的元素,但是不同对象的时候,例如我new两个对象,两个对象里面person1.name=“小明”,person2.name=“小明”,这个时候,由于他们俩是完全不同的对象,地址值肯定不同,equals会返回false,导致集合中存入相同的元素。
  2. 当不重写hashcode,只重写equals方法的时候
    首先,还是一样的流程,当需要将元素put进集合的时候,会首先调用hashcode方法来比对是否相同,此时获取的是当前元素内存地址值的随机数,如果此时有两个内容值完全相同,但是两个不同对象的时候,他会因为两个对象内存地址不同,而获取到不同的hashcode,因此直接将元素放入集合,这样就直接不会再走equals判断,即使重写了equals逻辑也不会再有任何作用。

总结:综上所述,当我们使用hashmap或者hashset这类集合存放对象的时候,一定要同时重写hashcode和equals方法,否则一定会出现存放重复元素的情况发生,一般来说,我们使用hashmap的时候,key可以设置为String类型的,因为String默认帮我们重写了hashcode和equals方法,并且String在创建的时候,不会再堆内存中占用空间,会在字符串常量池中寻找是否有这样的字符串,有的话直接返回,没有的话,创建直接再返回。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值