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!
Simply put, hashCode() returns an integer value, generated by a hashing algorithm. Objects that are equal (according to their equals()) must return the same hash code. Different objects do not need to return different hash codes.
In Java, hashCode() by default is a native method, which means that the method has a modifier 'native', when it is implemented directly in the native code in the JVM. Used to digest all the data stored in an instance of the class into a single hash value i.e., a 32-bit signed integer.
Basically the default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. If look into the source of Object class , you will find the following code for the hashCode. public native int hashCode();
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.
It takes a 64 bit number, splits it half, and xors the two halves together (essentially).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With