hashcode代码的解析以及为啥要取31作为系数

在hashcode中,总而言之就是要产生尽可能不重复的hashCode值

下图的 value.length 为你传入的String字符串的长度,同理可推(传入的是 String a = "abcde" ),长度就为5

  val[i]其实就是传入字符串的ascii值,如果传入的位abcde,则val[1]=97,val[2]=98;

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

这个算法写的很巧妙,假设传入的是abcde,则运行结果其实如下:

a*31^4+b*31^3+c*31^2+d*31^1+e*31^0。也就是一个31进制的数转换成了一个10进制的数。

关于这个系数31,这个网上讲的很多,下面是官方的说法:(其实使用31是有一定争议的)

之所以使用 31, 是因为他是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。这个公式可以很简单的推导出来。

下面这篇文章介绍了两个结论:
1.基数要用质数
质数的特性(只有1和自己是因子)能够使得它和其他数相乘后得到的结果比其他方式更容易产成唯一性,也就是hash code值的冲突概率最小。
2.选择31是观测分布结果后的一个选择,不清楚原因,但的确有利。

http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/

如果面试问起 选择31的原因,那么你就说上面两个结论,如果再往深究,就是数学方面的范畴了

还有很多人会疑惑就是--------怎么都找不到重复的hashCode的例子。下面来一个

String a="Aa";String b="BB";

int c=a.hashCode();   2122  int d=b.hashCode();2112  所得hashCode就是重复的了

猜你喜欢

转载自blog.csdn.net/qq_38983577/article/details/81741938