Wednesday, August 31, 2011

Implementing and Testing HashCode and Equals Methods on Collections

Check it out! Below is code for a "string set": that is, a collection of strings in Java, which extends the HashSet class. Along the way, it will show you how to override the equals() and hashCode() methods. You need the former in order to give "logical" rather than "instance" equality. In turn, logically equivalent instances need to give identical hashCodes, meaning that the method also needs to be overrode.

I followed Java in a Nutshell's "recipe for a high-quality equals method" (p. 33). To test its validity, I wrote a method to ensure that an instance of StringSet:
  1. Was equal to itself
  2. Was not equal to another class of object
  3. Was equal to another StringSet instance which contained identical strings and the same number of strings (and vice versa)
  4. Was not equal to a StringSet with a different number of strings
  5. Was not equal to a StringSet instance which did not contain identical strings
The proper way to test would be to ensure that the equals method adheres to its general contract by implementing an equivalence relation: that it is reflexive, symmetric and transitive. Test 1 confirms reflexivity, test 3 confirms the symmetry. Transitivity testing is left as an exercise for the reader. ;)

Additionally, the contract calls for consistency and for non-null to return false.

It is easy to test the hashCode function. Simply create two logically equivalent instances and check that they produce the same result.

One problem I had, which I haven't resolved, is with the second constructor, which takes a collection as a parameter, to be added to the StringSet. This should've been very simple, and I thought my code was correct, as no exceptions were thrown. I don't get any input mismatch errors, but the ArrayList I try to pass it cannot be accessed. Other than that, the program is working wonderfully.


No comments:

Post a Comment