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
intvariable calledresult. - Compute an
inthashcodecfor 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 resultinglongas in above. - If the field is an object reference and this class's
equalsmethod compares the field by recursively invokingequals, recursively invokehashCodeon 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.hashCodemethods added in release 1.5.
- If the field is a
- Combine the hashcode
cintoresultas follows:result = 31 * result + c;
加载中,请稍侯......
精彩评论