About NewTechnoBuzz
Advertise
Contact Us

Tuesday, August 5, 2014

Overriding equals() and hashCode() method in Java

equals() and hashCode() methods in Java are two fundamental method declared in Object class. equals() method is used to compare equality of Objects while hashCode() method is used to generate an integer that represents the memory address of object.

The concept of overriding equals() and hashCode() methods in Java is used while inserting and retrieving Object from collections like HashMap etc.(How HashMap works in Java). equals() method is also used to prevent duplicates in HashSet and other Set implementation. The default implementation of equals() method compares the memory location of objects of class and only return true if both the objects are pointing to same memory location (i.e. essentially they are same object).

Java recommends to override equals and hashCode method if equality is going to be define by logical way or via some business logic. Since HashMap and Hashtable in Java relies on equals() and hashCode() method for comparing keys and values. Java provides following rules to override equals method in Java:
  • Reflexive : The object must be equal to itself.
  • Symmetric : If obj1.equals(obj2) is true then obj2.equals(obj1) must be true.
  • Transitive : if obj1.equals(obj2) is true and obj2.equals(obj3) is true then obj3.equals(onj1) must be true.
  • Consistent : Multiple invocation of equals() method must result same value until any of properties are modified.
  • Null comparison : Comparison of any object to null must be false and should not result in NullPointerException. For example obj1.equals(null) must be false. How to avoid NullPointerException in Java.

equals() and hashCode() contract

The contract of hasCode() and equals() method in Java is stated below:
  • If two objects are equal by equals() method then their hashcode values must be same.
  • If two objects are not equal by equals() method then their hashcode values could be same or different.

Steps to override equals() method in Java

  • If the reference to this object is the same as the reference to the argument object, return true.
  • If the argument is null, return false.
  • If the objects are not from the same class, return false. To determine an object's class, we use getClass().
  • Cast the argument from Object to specified class. To read, see ClassCastException in Java
  • Compare individual attribute starting with numeric attribute because comparing numeric attribute is fast and use short circuit operator for combining checks. If first field does not match, then return false. It’s also worth to remember doing null check on individual attribute before calling equals() method on them recursively to avoid NullPointerException during equals check in Java.

Example of overriding equals() method in Java

Let's implement equals() method for the class Person as follows:
class Person 
{
  private String firstName;
  private String lastName;
  private int id;
 
  public Person(String firstName, String lastName, int id)
  {
    this.firstName = firstName;
    this.lastName = lastName;
    this.id = id;
  }
 
  @Override
  public boolean equals(Object obj) {
      if (obj == this) {
          return true;
      }
      if (obj == null || obj.getClass() != this.getClass()) {
          return false;
      }

      Person guest = (Person) obj;
      return id == guest.id
              && (firstName == guest.firstName 
                   || (firstName != null && firstName.equals(guest.getFirstName())))
              && (lastName == guest.lastName 
                   || (lastName != null && lastName .equals(guest.getLastName())));
  }

  @Override
  public int hashCode() {
      final int prime = 29;
      int result = 1;
      result = prime * result
              + ((firstName == null) ? 0 : firstName.hashCode());
      result = prime * result + id;
      result = prime * result
              + ((lastName == null) ? 0 : lastName.hashCode());
      return result;
  }
}
 
public class Demo
{
  public static void main(String args[])
  {
    Person p1 = new Person("Anushka", "Krishan", 7);
    Person p2 = new Person("Anushka", "Krishan", 7);
    System.out.println(p1.equals(p2));
    System.out.println(p1.equals(p1));
    System.out.println(p2.equals(p1));
  }
}
 
OUTPUT
======
D:\JavaPrograms>javac Demo.java
D:\JavaPrograms>java Demo
true
true
true

Common errors while overriding equals() method in Java

I have seen many programmers making mistake while overriding equals() method in Java. Here I am listing some of common mistakes that I observed while analyzing code in Java:
  • Somestimes, programmers overload the equals() method instead of overriding. The syntax of equals method defined in Object class is public boolean equals(Object obj) but many people unintentionally, overloads equals method by writing public boolean equals(Person obj), instead of using Object as argument they use there class name.
    @Override annotation which can be used to tell compiler that you are overriding a method and compiler will be able to detect this error during compile time.
  • Second mistake, is not doing null check for member variables which results in NullPointerException during equals() invocation.
    firstName == guest.firstName || (firstName != null && firstName.equals(guest.firstName)));
    
  • Third common mistake is not to override hashCode() method and only overriding equals() method. This makes problem while performing operation on collections like HashSet and HashMap etc. You must have to override both equals() and hashCode() method in Java. To read more see , How HashMap works in Java.

That’s all about overriding equals() and hashcode() methods in Java. Please provide your valuable suggestions and feedback.


0 comments