hashcode() and equals() contract in Java

Hash Code
Photo by Mari Helin on Unsplash

In last article, we saw the implementation of Hashtable. Before moving on to HashMap and its implementation let’s get to know about two primary and most used methods by java developer: equals() and hashCode(). These methods are also underlying core for both Hashtable and HashMap.

public boolean equals(Object obj)
public int hashCode()

Both methods are part of Object class in java. This is the root of the class hierarchy. Every class has Object class as a superclass. All objects, including arrays, implement the methods of this class.

As per Javadoc equals()method indicates whether some other object is “equal to” given object. The default implementation of this method provided by Object class checks if two object references point to the same memory location, this comparison is known as a shallow comparison. It is called shallow comparison because the class doesn’t have any data members thus, comparison only happens on given objects references. The sub-class have their own implementation of this method as they need data member or state of the object also to be compared, such comparison is known as deep comparison.

equals() method implements an equivalence relation i.e reflexive, symmetric, transitive, consistent (refer Javadoc for these properties elaboration). One important point about this function is that whenever any object is compared against null it always returns false and not NullPointerException.

As per Javadoc hashcode() method returns a hash code value as an integer for the object. Hashcode value is mostly used in hashing based collections like Hashtable, HashMap, HashSet, etc. Whenever this method is invoked on the same object it should always return in the same value of integer unless the state of the object has changed or it might not be same between multiple executions of the application.

Let’s talk about the equals() and hashCode() contract:

1. If two objects are depicted equal by equals() method then there hashcode must be same.

2. If two objects are not equal by equals() method then there hashcode could be same or different.

So in simple terms, the contract is that if obj1.equals(obj2) then obj1.hashCode() == obj2.hashCode()

So, it is generally necessary to override the hashCode() method whenever equals() method is overridden, so as to maintain the above contract. Let’s see how to override these methods. Few points to note before overriding these methods respectively:

  1. Do this(i.e current object reference) check: if yes then return true.

Points to remember while overriding hashcode() method:

  1. Do check null: Before calling the method on members or fields to avoid NullPointerException, remember to check null if a member is null then return zero.

If you don’t override method properly your Object may not function correctly on hash-based collections, always tries to use effective hashcode implementation. IDEs like Eclipse, IntelliJ Idea provide the implementation use them as they are generally good enough to generate good hash code. For IntelliJ Idea, one can press command + N(Code -> Generate) and choose the hashCode() method.

Now, we know things to ponder before overriding let’s take a look at an example, in the below code I have used IntelliJ Idea to override these methods for me.

https://gist.github.com/lucifercr07/b0e1adbaed2de5fdff7b7494ad6ae7e2

Few quirks of these functions:

  1. Equal objects must produce the same hash code as long as they are equal, however unequal objects may not produce distinct hash codes.

Computers are all I want to know about.