Sumedh
Sumedh

Reputation: 435

Testing / Profiling a hashcode function for java hashmap

How 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?

Upvotes: 2

Views: 548

Answers (2)

WhiteFang34
WhiteFang34

Reputation: 72039

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;

Upvotes: 2

A Lee
A Lee

Reputation: 8066

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.

Upvotes: 3

Related Questions