DIY主题讨论20:哈希码的计算

DIY主题讨论20:哈希码的计算

1)自主选择一个类,说明它hashCode方法的设计理念和代码核心逻辑。
2) 举例说明。

HashCode

hashCode意义
在编写类的时候,如果覆盖了Object的equals方法,那么必须要覆盖hashCode方法,并且如果两个对象用equals方法比较返回true,那么这两个对象hashCode返回的值也必须是相等的,并且对于同一个对象,equals方法需要比较的属性值没有被修改,那么每次调用hashCode返回的值应该是一致的。

hashCode的主要目的就是为了提高诸如java.util.HashMap这样的散列表(hash table)的性能,散列表(hash table)需要保证集合的不重复,每个新加入的元素都要跟已经存在的元素不相等,一个个equals显然性能很差,所以引入hashCode。

hashCode方法的设计理念

  1. 重写equals()而重写hashCode(),重写hashCode()而重写equals()
  2. 将hashCode分为两种:单个类的hashCode和容器类(集合数组)的hashCode
  3. hashCode设计核心公式:s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1],乘法因子是31
  4. hash算法乘法因子需要时素数,且越大越好
  5. 乘法因子是31原因:计算机计算31比较快,31 * i = (i << 5) - i ,另一原因对超过5W个英文单词做测试,在取31情况下,碰撞的次数都不超过7次
  6. hash算法设计理念核心是降低冲突率,不同对象的hashCode尽量不要相等

hashCode代码核心逻辑(举例——Arrays)

为什么重写HashCode?

在Arrays重写了long、int、short、char、byte、boolean、float、double、Object,8个基本类型和Object类型的hashCode,在这个类中我想是因为可以提供每种类型的equals()比较方法而重写hashCode,如果不重写equals(),那么Arrays是个数组对象,Object对象使用内存地址来作为hashCode,两个相同值的Arrays对象会应为内存地址不同而不相等,因此需要重写equals()方法,进而需要重写hashCode方法。

HashCode方法逻辑
  1. 空Arrays的hashCode为0,只有一个对象,且对象为null的hashCode为0
  2. 非空Arrays遍历每个元素得到hashCode
  3. Arrays得出的hashCode与List得出的hashCode是一样的
  4. Arrays.hashCode()会计算一维数组元素的hashCode,如果是多维数组,那么需要递归进行hashCode的计算,使用Arrays.deepHashCode(Object[])方法。
  5. 循环内部基本计算公式 result = 31 * result + elementHash;

计算逻辑

  • 如果是long值,则elementHash = (int)(f ^ (f >>> 32))
  • 如果是int值,则elementHash = int值
  • 如果是short值,则elementHash = short值
  • 如果是char值,则elementHash = char值
  • 如果是byte值,则elementHash = byte值
  • 如果是boolean值,则elementHash = element ? 1231 : 1237,附注boolean的hashCode使用1231和1237
  • 如果是float值,则elementHash = Float.floatToIntBits(f)
  • 如果是double值,则elementHash = (int)(Double.doubleToLongBits(f) ^ (Double.doubleToLongBits(f) >>> 32));
  • 如果是Object值,则elementHash = element.hashCode()

long与double都使用了f ^ (f >>> 32)),因为long与double都是64位,需要转换为一个int数字——32位

思考

在jdk源码中,都有哪些类重写类hashCode,为什么?
equals方法的设计理念和代码核心逻辑?

参考

https://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier
https://m.imooc.com/article/22958
https://blog.csdn.net/qq_21251983/article/details/52164403

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值