Testing / Profiling a hashcode function for java hashmap
Ho开发者_如何学Pythonw do I test / profile a hashCode() implementation in Java? i.e. is it distributing my test data reasonably evenly etc? Is there any simple crude way in java API itself?
Map<Integer, Integer> hashCodes = new HashMap<Integer, Integer>();
for (YourHashcodedClass testData: largeCollectionOfTestData) {
Integer hashCode = Integer.valueOf(testData.hashCode());
Integer occurrences = hashCodes.get(hashCode);
if (occurrences == null) {
occurrences = 0;
}
hashCodes.put(hashCode, occurrences+1);
}
Then analyze your map for collisions.
Honestly, you shouldn't have to profile or test the distribution of your hashCode()
method if you follow best practices. See the hash code recipe below from Effective Java. Furthermore even if you don't write it too well, the HashMap
implementation rehashes your result to reduce collisions:
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);
}
You can also use HashCodeBuilder
from Apache Commons Lang to build the hash code for you.
Effective Java 2nd Edition hash code recipe
- Store some constant nonzero value, say 17, in an
int
variable calledresult
. - Compute an
int
hashcodec
for each field:- If the field is a
boolean
, compute(f ? 1 : 0)
- If the field is a
byte, char, short, int
, compute(int) f
- If the field is a
long
, compute(int) (f ^ (f >>> 32))
- If the field is a
float
, computeFloat.floatToIntBits(f)
- If the field is a
double
, computeDouble.doubleToLongBits(f)
, then hash the resultinglong
as in above. - If the field is an object reference and this class's
equals
method compares the field by recursively invokingequals
, recursively invokehashCode
on the field. If the value of the field isnull
, return 0. - If the field is an array, treat it as if each element is a separate field. If every element in an array field is significant, you can use one of the
Arrays.hashCode
methods added in release 1.5.
- If the field is a
- Combine the hashcode
c
intoresult
as follows:result = 31 * result + c;
精彩评论