有效Java hashCode()实现中的位移

时间:2010-05-13 14:32:55

标签: java hashcode

我想知道是否有人可以详细解释什么

(int)(l ^ (l >>> 32));

在下面的hashcode实现中(由eclipse生成,但与Effective Java相同):

private int i;
private char c; 
private boolean b;
private short s;
private long l;
private double d;
private float f;

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + i;
    result = prime * result + s;
    result = prime * result + (b ? 1231 : 1237);
    result = prime * result + c;
    long t = Double.doubleToLongBits(d);
    result = prime * result + (int) (t ^ (t >>> 32));
    result = prime * result + Float.floatToIntBits(f);
    result = prime * result + (int) (l ^ (l >>> 32));
    return result;
}

谢谢!

3 个答案:

答案 0 :(得分:31)

基本上,它使用最低32位对一个长的前32位进行异或。这是一个爆炸版本:

// Unsigned shift by 32 bits, so top 32 bits of topBits will be 0,
// bottom 32 bits of topBits will be the top 32 bits of l
long topBits = l >>> 32;

// XOR topBits with l; the top 32 bits will effectively be left
// alone, but that doesn't matter because of the next step. The
// bottom 32 bits will be the XOR of the top and bottom 32 bits of l
long xor = l ^ topBits;

// Convert the long to an int - this basically ditches the top 32 bits
int hash = (int) xor;

回答您的评论:您有一个long值,必须将其转换为int才能成为哈希的一部分(结果必须只有32位)。你打算怎么做?你可以只取底部的32位 - 但这意味着中的前32位的变化将被忽略,这不会使它成为一个非常好的散列。这样,输入总是的单个位的更改会导致散列的单个位的更改。不可否认,您仍然可以轻松地获得冲突 - 例如,更改两个位7和39,或者将任何其他位对32位置分开 - 但是这种情况肯定是这样的,因为您来自2 64 可能值为2 32

答案 1 :(得分:8)

它需要一个64位的数字,将它分成两半,然后将两半(基本上)合在一起。

答案 2 :(得分:4)

它需要一个(64位)long l,独占或者将上半部分和下半部分(每个32位)放入64位结果的底部32位,然后需要仅使用(int)强制转换的底部32位。