在 http://www.docjar.com/html/api/java/util/HashMap.java.html 上找到此代码在搜索 HashMap 实现之后。
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 }
有人可以阐明这一点吗?评论告诉我们为什么这段代码在这里,但我想了解这如何改善错误的散列值以及它如何保证位置的数量有限碰撞。这些魔数(Magic Number)是什么意思?
最佳答案
为了使它有意义,它必须与对 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
这样的哈希函数不可能以其作者可见的任何方式“坏”。但是,如果您将它与 map 分配桶的方式结合起来,boom,MapFail(tm)。
如果您记住 h 是一个 32 位数字,那么它们根本就不是魔数(Magic Number)。它系统地将数字的最高有效位向右异或到最低有效位。这样做的目的是,当以二进制形式查看时,“跨越”它的任何地方出现的数字“差异”在最低有效位中变得可见。
冲突变得有界,因为具有相同相关 LSB 的不同数字的数量现在明显有界,因为二进制表示中任何地方出现的任何差异都被压缩到对存储重要的位中。
关于java - OpenJDK的rehashing机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7922019/