What Issues Should be Considered When Overriding equals and hashCode in Java?

What Issues Should be Considered When Overriding equals and hashCode in Java?

When overriding equals() and hashCode() in Java, make sure that if both of the two objects are equal according to equals(), their hashCode() values must also be equal, so that they maintain the contract of hash-based collections. 

In this blog, we will discuss the equals() and the hashCode() methods in Java and what problems one can face when overriding them.

Table of Contents:

What is the equals() method in Java?

The equals() method, by default, checks the object references of the two objects, but when it is overridden, it compares their field values. It returns true if both the objects point to the same memory location and returns false if not.

Syntax:

public boolean equals  (Object obj)

Example:

Java

Output:

What is the equals() method in Java

Explanation:  In the above code, three objects are created. Where obj1 and obj2 have the different object references, due to which, while comparing, they give the output as false. Whereas,  the obj1 and the obj3 have the same memory location, hence they give the output as true.

Master Java Today - Accelerate Your Future
Enroll Now and Transform Your Future
quiz-icon

What is the hashCode() method in Java?

The hashCode() method in Java returns an integer value that helps identify objects in hash-based collections like HashMap or HashSet.

The hashCode() value is not necessary to be unique for every object. However, the default implementation typically returns a hash derived from the object’s memory address. The value is computed when the method is called, not at object creation time.

Syntax:

public int hashCode()

Example:

Java

Output:

What is the hashCode() method in Java

Explanation: In the above code, obj1 and obj2 have their two different values being generated by the hashCode() method. As both the objects have different memory locations.

Note: Both of these methods are found in the java.lang.Object.

What Issues should be considered when overriding equals and hashCode in Java?

Issue 1: Overriding both equals() and hashCode() methods

  • If two objects are the same, then the hashCode method will return the same value for both objects. 
  • If the hashCode method is used more than one time, on the same object during a single execution, it should return the same integer value. This value should remain the same from one execution of the application to the next.
  • It is not required that if two objects are not equal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects should give different integer values. Hence, producing different integer values for the unequal objects can improve the performance of the hash tables.

Example:

Java

Output:

Case 1: Overriding both equals() and hashCode() methods
Unlock Your Future in Java
Start Your Java Journey for Free Today
quiz-icon

Issue 2: Overriding the equals() method

  • Overriding the equals() method without overriding hashCode() may lead to the generation of two different hashCode values for the equal object, which violates the hashCode contract. 
  • If equals() is overridden but hashCode() is not, two equal objects might be treated as different in hash-based collections, leading to unexpected behavior, such as duplicate entries or failure to retrieve stored objects
  • It should be noted that if the class object is never used in any of the hash-based collections, then it doesn’t matter if hashCode() is overridden or not.

Example:

Java

Output:

Case 2: Overriding the equals() method

Issue 3: Overriding the hashCode() method

  • If only the hashCode() method is overridden, then both objects will hash to the same bucket as they will have the same hashCode. 
  • But as the equals method is not overridden, it will search for a certain object if found, then it will be returned; otherwise, a new object will be inserted into the collection, even if it is logically equal to an existing one. 
  • This can lead to duplicate objects in HashSet or incorrect key lookups in HashMap, violating the expected behavior of hash-based collections.

Example:

Java

Output:

Case 3: Overriding the hashCode() method

When and why to override the equals() and the hashCode() methods in Java?

You should override the equals() and hashCode() methods in Java when you want to compare the objects based on their content rather than their memory address, especially when storing them in collections like HashSet, HashMap, or Hashtable.

Hash codes affect how objects are placed into buckets in hash-based data structures, but they do not determine the actual memory location of the object.

Overriding equals() ensures that the objects with the same content are equal. If you override equals() only, hash-based collections will not find the duplicates correctly, which can lead to unexpected behaviour.

Similarly, if you override only hashCode() but not equals(), then the objects with the same hash code can be considered unequal because equals() continues to use the default reference equality.

Best Practices for implementing equals() and hashCode() methods in Java

1. Override Both Methods Together to Avoid Unexpected Errors
Overriding only one of the methods equals() or hashCode() can lead to unexpected behavior when using collections like HashMap, HashSet, and Hashtable.

2. Access fields in a way that maintains encapsulation and avoids side effects.
Do not change or access the variables directly. You can use the Getters and Setters, as they control how the data will be read or changed, hence the class remains the same

3. Use instanceof Before Comparing Objects
Before comparing, use the instanceof operator to ensure that the object that is compared is of the correct type. This will prevent ClassCastException.

4. Follow the Contract of Both Methods
Java has some rules for both the equals() and hashCode() methods. These are ;

Equals Contract:

  • Reflexive: x.equals(x) must return true.
  • Symmetric: If x.equals(y) is true, then y.equals(x) is also true.
  • Transitive: If x.equals(y) and y.equals(z), then x.equals(z)  is also true.
  • Consistent: If x.equals(y) is true once, it must remain true unless it is changed.
  • Null-safety: x.equals(null) must return false.

Hashcode Contract:

  • If two objects are equal (equals() returns true), their hashCode() values must also be the equal.
  • If two objects are different, their hashCode() values are different, which can improve the performance of hash-based collections.
  • The hashCode() method must return the same value for an object.

5. Consistency with equals()
If any two objects are equal, their hashCode() should always return the same value.

6. Performance
A good hashCode() will distribute the objects evenly in the hash tables, which will make the operations like adding, removing, or finding items faster.

7. Immutability

Do not change the values while using the hashCode(), as changing the values can lead to errors.

8. Relevant Fields

Only use the fields that are important for equality, to make it efficient.

9. Null Handling
Make sure that both of the methods handle the null properly to avoid errors.

10. Consistency
Both methods should return the same value every time they are called, until the object is changed.

Get 100% Hike!

Master Most in Demand Skills Now!

Conclusion

Overriding both the equals() and the hashCode() methods helps to ensure the correct behavior when comparing objects based on their values, like HashSet or HashMap. The equals() method helps check if objects are equal, while hashCode() helps them to store correctly. You should override both methods together to prevent issues like duplicates. Using getter methods and checking object types can help to maintain the proper functionality of the code.

If you want to learn more about Java, you can refer to our Java Course.

What Issues Should be Considered When Overriding equals and hashCode in Java – FAQs

Q1. When to override the equals and the hashCode in Java?

When working with collections, you should override them. 

Q2. What is the importance of hashCode() and equals() methods?

They are used to define object equality and to enable the effective use of objects in hash-based data structures such as HashMap, HashSet, etc

Q3. Should I always override equals?

You should override equals if and only if your objects have a logical identity that is independent of their physical identity. 

Q4. What is the difference between == and equals() in Java?

string.equals() method compares the content equality of two strings while the == operator compares the reference or memory location of objects 

Q5. Can two objects have the same hashcode but they are not be equal?

If two objects have the same hashcode, then they are NOT necessarily equal.

Q6. What happens if we don't override the run method?

No code will be executed when a thread is started using that class.

About the Author

Technical Research Analyst - Full Stack Development

Kislay is a Technical Research Analyst and Full Stack Developer with expertise in crafting Mobile applications from inception to deployment. Proficient in Android development, IOS development, HTML, CSS, JavaScript, React, Angular, MySQL, and MongoDB, he’s committed to enhancing user experiences through intuitive websites and advanced mobile applications.

Full Stack Developer Course Banner