zoukankan      html  css  js  c++  java
  • 为什么在定义hashcode时要使用31这个数呢?

    public int hashCode() {

    int h = hash;
    int len = count;
    if (h == 0 && len > 0) {
    int off = offset;
    char val[] = value;
    for (int i = 0; i < len; i++) {
    h = 31*h + val[off++];
    }
    hash = h;
    }
    return h;
    }

    该函数是我看的函数接口源码,为什么要使用31这个数呢?

    其实上面的实现也可以总结成数数里面下面这样的公式:

    s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]

    原因如下:

    A.31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终的出来的结果只能被素数本身和被乘数还有1来整除!。(减少冲突)

    B.31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化.(提高算法效率)

    C.选择系数的时候要选择尽量大的系数。因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)

    D.并且31只占用5bits,相乘造成数据溢出的概率较小。
     s[i]是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化

  • 相关阅读:
    使用layui报错:Uncaught TypeError: Cannot create property 'LAY_TABLE_INDEX' on number '2
    mongodb安装教程
    PDF,Word,Markdown,HTML ,Doc文件格式的相互转换
    Go To Oracle
    spark、standalone集群 (2)集群zookeeper 热备
    spark、standalone集群 (1)
    tomcat8.0部署启动
    mysql5.7以上安装
    spark单击 搭建
    自定义标签
  • 原文地址:https://www.cnblogs.com/liuzhuqing/p/7480408.html
Copyright © 2011-2022 走看看