OpenJDK的重组机制

时间:2011-10-27 20:34:37

标签: java hashmap bit-manipulation hash openjdk

在搜索HashMap实现后,在http://www.docjar.com/html/api/java/util/HashMap.java.html上找到此代码。

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

有人可以对此有所了解吗?评论告诉我们为什么此代码在这里,但我想了解如何改善糟糕的哈希值如何保证这些位置的有限数量碰撞即可。这些幻数意味着什么?

1 个答案:

答案 0 :(得分:22)

为了使它具有任何意义,它必须与理解HashMap如何将内容分配到存储桶中相结合。这是选择存储桶索引的简单函数:

static int indexFor(int h, int length) {
    return h & (length-1);
}

所以你可以看到,默认表大小为16,只有哈希的4个最低有效位实际上对分配桶很重要! (16 - 1 = 15,用1111b掩盖散列)

如果你的hashCode函数返回了,这显然是坏消息:

10101100110101010101111010111111

01111100010111011001111010111111

11000000010100000001111010111111
//etc etc etc

这样的哈希函数不会以其作者可见的任何方式“坏”。但是如果你把它与地图分配桶的方式结合起来,繁荣,MapFail(tm)。

如果您记住h是32位数字,那么这些数字根本不是 magic 。它系统地将数字的最高有效位向右扫描到最低有效位。其目的是,当以二进制形式查看时,在“跨越”它的任何地方出现的数字的“差异”在最低有效位中变得可见。

碰撞变得有限,因为具有相同相关LSB的不同数字的数量现在明显受限,因为在二进制表示中的任何地方出现的任何差异都被压缩为对于桶的重要位。