理解奇怪的Java哈希函数

pai*_*lee 33 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);
}
Run Code Online (Sandbox Code Playgroud)

phi*_*lwb 49

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' ) );
}
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

11111111111111111111111111111111
00000000000000000000111111111111
00000000000011111111111111111111
00000000000011111111000000000000
11111111111100000000111111111111
00000001111111111110000000011111
00001111111111110000000011111111
00001110000000001110000011100000
11110001111100001110111100011111
Run Code Online (Sandbox Code Playgroud)

因此,代码将哈希函数分解为步骤,以便您可以看到正在发生的事情.20个位置的第一个移位xor和12个位置的第二个移位创建了一个掩码,可以翻转int的底部20位的0或更多.因此,您可以在底部位中插入一些随机性,以利用可能更好的分布式高位.然后通过xor将其应用于原始值,以将该随机性添加到较低位.7个位置的第二个移位x或4个位置的移位创建了一个掩码,可以翻转底部28位的0或更多,这通过利用先前的xor将一些随机性再次带到较低位和一些较重要的位.已经解决了较低位的一些分布问题.最终结果是通过散列值更平滑地分配比特.

由于java中的hashmap通过将散列与桶的数量组合来计算桶索引,因此需要均匀分布散列值的较低位以将条目均匀地分布到每个桶中.

至于证明这限制了碰撞次数的说法,我没有任何输入.另外,请参阅此处以获取有关构建散列函数的一些有用信息以及有关为什么两个数字的xor趋向于在结果中随机分配位的一些详细信息.


Sti*_*sis 6

>>> 是零填充的零位移.

^ 是异或.

XOR也称为独占或 - 它是一个组合两个数字的数学运算符.见http://en.wikipedia.org/wiki/Exclusive_or

正确的bithift by n就像n从数字中删除最低位一样.因此,如果数字是00010111,并且你将它右移1,你就会得到00001011.


Mic*_*rdt 5

这是一篇讨论整数哈希函数及其设计考虑因素的文章。不是很详细,但重点是:

操作必须使用一系列计算来实现雪崩。雪崩意味着输入中的单个位差异将使大约 1/2 的输出位不同。

基本上,补充哈希函数的目标是消除输入中的任何规律性,因为这些规律性会导致哈希表退化。