以下是java.util.HashMap
中哈希函数的源代码。评论很好地解释了它的成就。 但是如何? ^
和>>>
运营商在做什么? 有人可以解释代码实际上如何评论说什么
/**
* Applies a supplemental hash function to a given hashCode, which
* defends against poor quality hash functions. This is critical
* because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/
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);
}
答案 0 :(得分:48)
Dunno'关于英语,但这里有一些代码和示例输出:
public static void main ( String[] args ) {
int h = 0xffffffff;
int h1 = h >>> 20;
int h2 = h >>> 12;
int h3 = h1 ^ h2;
int h4 = h ^ h3;
int h5 = h4 >>> 7;
int h6 = h4 >>> 4;
int h7 = h5 ^ h6;
int h8 = h4 ^ h7;
printBin ( h );
printBin ( h1 );
printBin ( h2 );
printBin ( h3 );
printBin ( h4 );
printBin ( h5 );
printBin ( h6 );
printBin ( h7 );
printBin ( h8 );
}
static void printBin ( int h ) {
System.out.println ( String.format ( "%32s",
Integer.toBinaryString ( h ) ).replace ( ' ', '0' ) );
}
打印哪些:
11111111111111111111111111111111
00000000000000000000111111111111
00000000000011111111111111111111
00000000000011111111000000000000
11111111111100000000111111111111
00000001111111111110000000011111
00001111111111110000000011111111
00001110000000001110000011100000
11110001111100001110111100011111
因此,代码将散列函数分解为步骤,以便您可以看到正在发生的事情。 20个位置的第一个移位xor和12个位置的第二个移位创建了一个掩码,可以翻转int的底部20位的0或更多。因此,您可以在底部位中插入一些随机性,以利用可能更好的分布式高位。然后通过xor将其应用于原始值,以将该随机性添加到较低位。 7个位置的第二个移位x或4个位置的移位创建了一个掩码,可以翻转底部28位的0或更多,这通过利用先前的xor将一些随机性再次带到较低位和一些较重要的位。已经解决了较低位的一些分布问题。最终结果是通过哈希值更平滑地分配比特。
由于java中的hashmap通过将哈希值与桶数相结合来计算桶索引,因此需要均匀分配哈希值的较低位以将条目均匀地分布到每个桶中。
至于证明这限制了碰撞次数的说法,我没有任何输入。另外,请参阅here以获取有关构建散列函数的一些有用信息,以及有关为什么两个数字的xor趋向于在结果中随机分配位的一些详细信息。
答案 1 :(得分:6)
>>>
是零填充的零位移。
^
是异或。
XOR
也称为独占或 - 它是一个组合两个数字的数学运算符。见http://en.wikipedia.org/wiki/Exclusive_or
n
的右移位就像从数字中删除n
最低位。因此,如果该数字为00010111
,并且您将其向右移动了1,那么您将获得00001011
。
答案 2 :(得分:4)
这是article that discusses integer hash functions以及它们设计的一些注意事项。它不是很详细,但重点是:
操作必须使用一系列计算来实现雪崩。 雪崩意味着输入中的一点差异将会产生 大约1/2的输出位是不同的。
基本上,目标是补充哈希函数删除输入中的任何规则,因为那些可能导致哈希表退化。
答案 3 :(得分:1)
^
为bitwise XOR,>>>
为bit shift。
答案 4 :(得分:0)
>>>
似乎是无符号右移位,^
是按位XOR
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
答案 5 :(得分:-1)
它是按位异或和无符号右移的组合。
有关详细说明,请参阅此处:http://www.roseindia.net/java/master-java/bitwise-bitshift-operators.shtml