一文彻底搞懂为什么重写equals还要重写hashcode?

hashcode

hashCode即散列码。散列码是用一个int值来代表对象,它是通过将该对象的某些信息进行转换而生成的。

Object类中默认的hashCode方法如下。

public native int hashCode();

这个方法返回的是一个整型类型的数值。
如果没有被重写的话,也就是Object类的方法,它返回的其实就是对象的地址

equals方法

在Object类中,查看其源码我们可以看到:

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

其作用和 == 一样,如果是引用类型的话都是对比两个变量的地址。

所以在其两个方法都没有被重写时,他们的效果是一样的。

java集合存取原理

在hashmap中是通过hashcode决定元素放入哪个索引(桶)中,然后通过equals判断和索引中中对应链表中的每个元素是否相同,如果有相同 ->不放,如果不相同 -> 放 ( jdk version >8尾插法、<8头插法)
如图:
在这里插入图片描述

假设有这么一种情况。我们新建两个对象,其属性值都一样。

  • 我们重写了其equals方法,而没有重写其hashcode方法,那么就会导致放入集合中时,由于两个对象的地址不一样,而其hashcode方法又没有被重写,他们俩会被放在不同的索引下。但其equals相等,他们的属性值一样,这显然是不合理的。

  • 如果在hashmap中如果只重写了hashcode没重写equals,如果我们添加两个相同内容的对象放入hashmap,添加完第一个后,添加第二个时,hash值和第一个相同,会走equals到同一个索引中找是否存在相同的元素,此时我们因为没重写equals,比较的是地址值(两个虽然内容相同的对象地址值是不同的),因此第二个相同的User也插入到了同一个索引中。(似乎这合乎规范,可以放到一个桶中)

Java核心技术卷1中 第172页说明:

  • Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回 true, 那么 x.hashCode( ) 就必须与 y.hashCode( ) 具有相同的值。 这足以说明 我们上述的第一种情况是不合理的。

可以推断出其逆否命题为:hashcode不等,equals一定不等

而hashcode相等,equals不一定相等

  • 对应情况二,如果equals相等,则对应该桶位有一个元素,也就是键值一样。
  • 如果equals不相等,则该桶则有两个元素。

equals不等,hashcode不一定不等

equals不等,一般hashcode也不相等,这是为了尽量减少哈希冲突。但为啥会出现相等的情况呢,因为hashcode是int类型,是有范围的,当数据量很大的情况下,难免会发生冲突,此时HashMap通过拉链法解决冲突。

当从map中获取equals不等的两个键时,由于它们的hashcode相同,所以计算到的下标值也相同,当定位到同一个桶位时,会在单链表上顺序查找,查找到的依据就是要查找的键与单链表上的键equals相等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值