有人能解释一下java是如何设计HashMap的吗;s hash()函数?

有人能解释一下java是如何设计HashMap的吗;s hash()函数?,java,hash,hashmap,Java,Hash,Hashmap,阅读JDK的源代码后,我发现HashMap的hash()函数似乎很有趣。其soucre代码如下: static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 a

阅读JDK的源代码后,我发现HashMap的
hash()
函数似乎很有趣。其soucre代码如下:

    static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

参数
h
是放入
HashMap
Objects
中的hashCode。这种方法是如何工作的,为什么?为什么这种方法可以抵御糟糕的hashCode函数?

Hashtable使用质数的“经典”方法:要获得值的“索引”,您需要对键进行散列,并根据大小执行模数。以素数作为大小,会(通常)在索引上产生一个很好的分布(当然也取决于散列)

HashMap使用“二次幂”方法,这意味着大小是二次幂。原因是它应该比素数计算快。然而,由于二的幂不是质数,因此会有更多的冲突,特别是当哈希值具有相同的低位时

为什么??针对获取(bucket/slot)索引的大小执行的模数通过以下公式计算:hash&(size-1)(这正是HashMap中用于获取索引的内容!)。这基本上就是“二次幂”方法的问题:如果长度有限,例如HashMap的默认值16,则只使用最后一位,因此,具有相同低位的哈希值将产生相同的(bucket)索引。在16的情况下,只有最后4位用于计算索引

这就是为什么要计算一个额外的散列,基本上它会移动较高的位值,并使用较低的位值对其进行操作。数字20、12、7和4的原因,我真的不知道。它们过去可能有所不同(在Java1.5左右的版本中,哈希函数几乎没有什么不同)。我想还有更先进的文献。您可能会在各种算法相关文献中找到更多关于他们为什么使用数字的信息,例如

根据长度使用不同的算法(这是有意义的)

可能也很有趣。查看文章底部Joshua Bloch的反应:“替换二次散列函数(我在计算机的帮助下开发)具有很强的统计特性,几乎可以保证良好的桶分布。”)因此,如果你问我,这些数字来自Josh自己进行的某种分析,可能是谁知道谁在协助


因此:2的幂运算可以加快计算速度,但需要额外的散列计算,以便在插槽/存储桶之间有一个良好的分布。

谢谢您的完美答案