HashCode() and equals() method in Java

There is a contract between equals() and hashCode() method in Java, if two objects are equal by equals() method then their hashCode() must be equal i.e. two equivalent objects should have the same hashcode.

class Student {
   int id;
   Student(int id) {
      this.id = id;
   }
}

Assume s1 and s2 are two different objects of Student class. If s1.equals(s2) is true then s1.hashCode() == s2.hashCode() is always true.

java.lang.Object class equals() and hashCode() method follows above contract. Hence whenever we are overriding equals() method then compulaory we should override hashCode() method to satisfying above contract i.e. two equivalent objects should have same hashCode. If we don’t follow this contract then we won’t get any compile time error, or runtime exception but it is not a good programming practice.

In java.lang.String class equals() method is overridden for content comparision and hance hashCode() method is also overridden to generate hashcode value based on the content.

public class Test {
   public static void main(String[] args) {
      String s1 = new String("KnowProgram");
      String s2 = new String("KnowProgram");
      System.out.println(s1.equals(s2)); 
      System.out.println(s1.hashCode() == s2.hashCode());
      System.out.println(s1.hashCode());
      System.out.println(s2.hashCode());
   }
}

Output:-

true
true
2058267993
2058267993

In StringBuffer and StringBuilder classes equals() method is not overridden for content comparision, and hance hashCode() method is also not overriden.

public class Test {
   public static void main(String[] args) {
      StringBuilder s1 = new StringBuilder("KnowProgram");
      StringBuilder s2 = new StringBuilder("KnowProgram");
      System.out.println(s1.equals(s2)); 
      System.out.println(s1.hashCode() == s2.hashCode());
      System.out.println(s1.hashCode());
      System.out.println(s2.hashCode());
   }
}

Output:-

false
false
225534817
1878246837

Different cases,
1) If two objects are not equal by equals() method then their hashcode value may or may not be the same.

s1.equals(s2)s1.hashCode() == s2.hashCode()
truetrue
falsetrue/false


2) If the hashcode of two objects is equal then the equals() method return true or false.
3) If the hashcode of two objects is not equal then these objects are always not equal by the equals() method.

s1.hashCode() == s2.hashCode()s1.equals(s2)
truetrue/false
falsefalse

Based on which parameter we override equals() method, it is highly recommended to use same parameter while overriding hashCode() also.

In all collections class, wrapper classes, and string class the equals() method is overridden for content comparison. Hence it is highly recommended to override the equals() method in our class also for content comparison.

class Student {
   private int id;

   Student(int id) {
      this.id = id;
   }

   @Override
   public boolean equals(Object obj) {
      if(this == obj) return true;
      if(obj instanceof Student) {
         Student s = (Student) obj;
         return this.id == s.id;
      }
      return false;
   }

   @Override 
   public int hashCode() {
      return id;
   }
}

public class Test {
  public static void main(String[] args) {

     Student s1 = new Student(1001);
     Student s2 = new Student(1002);
     Student s3 = new Student(1001);
      
     // invoke hashCode() method
     System.out.println("hashCode():: " +
                    s1.hashCode() + " " +
                    s2.hashCode() + " " +
                    s3.hashCode() );

     // invoke equals() method
     System.out.println("equals():: " + 
                  s1.equals(s2) + " " +
                  s1.equals(s3) + " " +
                  s2.equals(s3) );
  }
}

Output:-

hashCode():: 1001 1002 1001
equals():: false true false

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or you find anything incorrect? Let us know in the comments. Thank you!

Leave a Reply