Java HashSet with Custom Objects – Mr. Joel Kemp

Damn you, Java!

If you want to use a hash-based (particularly a HashSet or HashMap) structure with a custom object, the class to be hashed needs to override 2 methods: public int hashCode(); and public boolean equals(Object o);. This has been explained time and time again on StackOverflow. But I just want to complain a little bit and stress one insanely important point about these functions!

The equals() function described above uses the @override annotation. This helps a ton! If you screw up the prototype, then you’re not overriding the proper function and the compiler complains!

For example, a common mistake:

public class Foo(){        //This function should if the current Foo object     //   is equal to the parameter object.    //COMPILER ERROR because the proper function to override is    //   public boolean equals (Object other);    @override    public boolean equals(Foo other){    }}

What’s great is that you actually get the compiler error! Of course, if you leave off the @override annotation, then the compiler thinks you’re defining a regular function equals() and it won’t complain!

The Important Point
Unfortunately, the hashCode() function does not use the @override annotation! You guessed it, if you screw up the prototype, then the compiler doesn’t utter a peep! It simply won’t use your function for computing the hash of the object and defaults to its non-ideal hashing function.

For example (an example that gave me a bald spot),

public class Foo(){        //Note the accidental typo: hashcode instead of hashCode    public int hashcode(){    }}

The compiler thinks you’re simply defining some regular function called “hashcode“! Since it didn’t find the “hashCode” function it wants to use for custom hashing, again, it defaults to its own hashing function.

What’s the Result of the Typo?
The objects in your HashMap or HashSet won’t be hashed properly. As a result, a simple check (using the contains() function) to see if an object is already within the map or set will always yield false. This is terrible, especially if you’re using hash-based structures to ensure unique sets of objects.

As you can imagine, tracking down the mistake is almost impossible. You’re more likely to think something is wrong with your custom hashing function’s body.

hashcode() is not hashCode()

Damn you, Java for not using the @override notation on one of the most important functions.