理解奇怪的Java哈希函数

时间:2012-02-17 20:47:13

标签: java hash

以下是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);
}

6 个答案:

答案 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