zoukankan      html  css  js  c++  java
  • hashCode方法里为什么选择数字31作为生成hashCode值的乘数


    前提:

      偶然的机会看到了大神的一篇博客,介绍的是hashCode()方法里为什么要用31这个数字作为生成hashCode的乘数。hashCode我在比较自定义类时曾经用到过 - 由于java默认比较的是类的地址值,每个对象一定是不同的,所以重写了hashCode()和equals()方法
    ,这样就会先根据类里的属性生成hashCode,如果生成的hashCode值相同,则在使用equals()比较属性的值。两者都相同则认为这两个对象相等。当是就对hashCode的生成很好奇,自己看了下源码也是懵懵懂懂。这下终于可以搞清楚了,开森,感谢大佬!

      hashCode()方法的源码:

    原因一:更少的乘积结果冲突

      31是质子数中一个“不大不小”的存在,如果你使用的是一个如2的较小质数,那么得出的乘积会在一个很小的范围,很容易造成哈希值的冲突。而如果选择一个100以上的质数,得出的哈希值会超出int的最大范围,这两种都不合适。而如果对超过 50,000 个英文单词(由两个不同版本的 Unix 字典合并而成)进行 hash code 运算,并使用常数 31, 33, 37, 39 和 41 作为乘子,每个常数算出的哈希值冲突数都小于7个(国外大神做的测试),那么这几个数就被作为生成hashCode值得备选乘数了。

    原因二:31可以被JVM优化

      JVM里最有效的计算方式就是进行位运算了:

    * 左移 << : 左边的最高位丢弃,右边补全0(把 << 左边的数据*2的移动次幂)。
    * 右移 >> : 把>>左边的数据/2的移动次幂。
    * 无符号右移 >>> : 无论最高位是0还是1,左边补齐0。   

           所以 : 31 * i = (i << 5) - i(左边  31*2=62,右边   2*2^5-2=62) - 两边相等,JVM就可以高效的进行计算啦。。。

      ps:以前家里人老说学号数理化,走遍全天下。貌似很有道理^_^

  • 相关阅读:
    DB2创建序列
    hibernate注解影射表
    自定义异常类一
    【JVM】java方法区
    【JVM】java棧
    (2)java堆内存
    (1)java虚拟机概念和结构图
    枚举应用五
    设计模式之命令模式学习理解
    eclipse中javadoc给项目生成api文档
  • 原文地址:https://www.cnblogs.com/0813lichenyu/p/8367103.html
Copyright © 2011-2022 走看看