开发者

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 called result.
  • Compute an int hashcode c 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, compute Float.floatToIntBits(f)
    • If the field is a double, compute Double.doubleToLongBits(f), then hash the resulting long as in above.
    • If the field is an object reference and this class's equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If the value of the field is null, 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.
  • Combine the hashcode c into result as follows: result = 31 * result + c;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜