Why : Overriding equals() and hashCode() in Java

Phani Kumar
5 min readJan 16, 2020

--

equals() and hashcode() are by default present in Java super class java.lang.Object.

Consider below example:Employee is a class that has 2 data members: id & name. Two emp objects are created (emp1,emp2). both objects have same id & name as below. but when i do equality check it returns false !!!!!!

So, in realtime we deal with objects like above or with more complex ones. , For example we want to check the equality of employee object by the id.

then ?? lets see that how. but before that lets see how equals() is defined from java docs.

equals(Object obj): public boolean equals(Object obj)

— Indicates whether some other object is “equal to” this one.

The default implementation provided by the JDK is based on memory location — two objects are equal if and only if they are stored in the same memory address.

From oracles java doc : —

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

Why we override equals() method?
The default implementation is not enough to satisfy business needs, especially if we’re talking about a huge application that considers two objects as equal when some business fact happens. ( like the above Employee example)

It needs to be overridden if we want to check the objects based on the property.

For example, we want to check the equality of employee object by the id.Then, we need to override the equals() method.

see below code with overriding equals method

Yes, now we are able achieve equality of objects.

Lets see side effects of overriding equals() method.

observe below example

i added these emp objects to a HashSet. Set should override the duplicate values and should return me only one object as both objects are same. but after overriding equals() you can see Set functionality is disturbed.

As per the Java documentation, developers should override both methods in order to achieve a fully working equality mechanism — it’s not enough to just implement the equals() method.

If two objects are equal according to the equals(Object) method, then calling the hashcode() method on each of the two objects must produce the same integer result.

hashcode():

public int hashCode()

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

From Oracles Java doc :

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

Consider below example with override hashCode()

So now Set is also fixed to it default behaviour.

Note:

  1. What if : Overriding only equals() without overriding hashCode():
  • causes the two equal instances to have unequal hash codes, that is in violation of the hashCode contract which we said above.
  • Since the default hashCode implementation in the Object class return distinct integers for distinct objects, if only equals() method is overridden,emp1 will be placed in one bucket, emp2 will be placed in another bucket. so emp1.hashCode() != emp2.hashCode(). So even though both emp1 and emp2 are equal, they don’t hash to the same bucket and both of them reside in the collection as separate keys.
  • It is worth noting that if the class instance is never used in any hash-based collections, then it doesn’t really matter if hashCode() is overriden or not!!

2 . What if : Overriding only hashCode() without overriding equals():

  • then , emp1 and emp2 objects will hash to the same bucket as they produces the same hash code. But since equals() is not overriden, when emp2 is added to Set , it iterates thorugh bucket looking if there is Employee such as emp2 ie : emp2.equals(emp1) will be false.

Conclusion:

As per the Java documentation, developers should override both methods in order to achieve a fully working equality mechanism — it’s not enough to just implement the equals() method.

If two objects are equal according to the equals(Object) method, then calling the hashcode() method on each of the two objects must produce the same integer result.

Thanks

./Phani

--

--