tags:

views:

281

answers:

3

I was wondering if someone could explain in detail what

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

does in the following hashcode implementation (generated by eclipse, but the same as 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;
}

Thanks!

+6  A: 

Basically it XORs the top 32 bits of a long with the bottom 32 bits. Here's an exploded version:

// 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;

To answer your comment: you have a long value which has to be converted into an int to be part of the hash (the result has to only be 32 bits). How are you going to do that? You could just take the bottom 32 bits - but then that means changes in only the top 32 bits would be ignored, which wouldn't make it a very good hash. This way, a change in a single bit of input always results in a change of a single bit of the hash. Admittedly you can still get collisions easily - change both bits 7 and 39, for example, or any other pair of bits 32 positions apart - but that's bound to be the case, given that you're going from 264 possible values to 232.

Jon Skeet
What's the reason for doing this? Would you not get an equally valid hashcode without doing it?
Scobal
@Scobal: I've expanded my answer to explain further.
Jon Skeet
A: 

It takes a 64 bit number, splits it half, and xors the two halves together (essentially).

glowcoder
+1  A: 

It takes a (64-bit) long l, exclusive-or's the top and bottom halves (of 32 bits each) into the bottom 32 bits of a 64-bit results, then takes only the bottom 32 bits with the (int) cast.

Alex Martelli