Equals and hashcode contract in java

Here we will see equals() and hashcode() contract in Java. Why it has been recommended to override both?

Equals and hashcode contract in java

Let’s see what is the contract between equals() and hashcode().

  • If two objects are equals using equals() method, their hashcode must be the same.
  • If two objects having the same hashcode they may or may not be equal using equals() method.

 

Let’s see an example.

package equalandhashcode;

class Book{
	String bookName;
	int bookId;
	public Book(String bookName, int bookId) {
		super();
		this.bookName = bookName;
		this.bookId = bookId;
	}
	
}
public class Test {
public static void main(String[] args) {
	Book b1 = new Book("book1",2);
	Book b2 = new Book("book1",2);
	System.out.println("b1 and b2 are equals "+b1.equals(b2));
	System.out.println("hashcode of b1       "+b1.hashCode());
	System.out.println("hashcode of b2       "+b2.hashCode());
	
			
}
}

 

Output is –

b1 and b2 are equals false
hashcode of b1 5433634
hashcode of b2 2430287

This is the expected output since b1 and b2 are different objects.

 

Let’s override equals() method only – Overriding equals() method with default eclipse logic.

package equalandhashcode;

class Book{
	String bookName;
	int bookId;
	public Book(String bookName, int bookId) {
		super();
		this.bookName = bookName;
		this.bookId = bookId;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Book other = (Book) obj;
		if (bookId != other.bookId)
			return false;
		if (bookName == null) {
			if (other.bookName != null)
				return false;
		} else if (!bookName.equals(other.bookName))
			return false;
		return true;
	}
	
	
	
}
public class Test {
public static void main(String[] args) {
	Book b1 = new Book("book1",2);
	Book b2 = new Book("book1",2);
	System.out.println("b1 and b2 are equals "+b1.equals(b2));
	System.out.println("hashcode of b1       "+b1.hashCode());
	System.out.println("hashcode of b2       "+b2.hashCode());
	
			
}
}

Output is –

b1 and b2 are equals true
hashcode of b1 5433634
hashcode of b2 2430287


Here we have something wrong. Don’t forget we have contract between equals() and hashcode() –

  • If two objects are equals using equals() method, their hashcode must be the same.

Here both objects are equals using equals() method but both have different hashcode. This is the reason it is recommended to override both.

Let’s override both. We will use eclipse provided default logic.


package equalandhashcode;

class Book{
	String bookName;
	int bookId;
	public Book(String bookName, int bookId) {
		super();
		this.bookName = bookName;
		this.bookId = bookId;
	}

	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + bookId;
		result = prime * result + ((bookName == null) ? 0 : bookName.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Book other = (Book) obj;
		if (bookId != other.bookId)
			return false;
		if (bookName == null) {
			if (other.bookName != null)
				return false;
		} else if (!bookName.equals(other.bookName))
			return false;
		return true;
	}
	
	
	
}
public class Test {
public static void main(String[] args) {
	Book b1 = new Book("book1",2);
	Book b2 = new Book("book1",2);
	System.out.println("b1 and b2 are equals "+b1.equals(b2));
	System.out.println("hashcode of b1       "+b1.hashCode());
	System.out.println("hashcode of b2       "+b2.hashCode());
	
			
}
}

 Output is –

b1 and b2 are equals true
hashcode of b1 93922919
hashcode of b2 93922919

 

Yes, now we are good. We have two objects equals using equals() method and also they have the same hashcode

In Interview, you may be asked what will happen if we only override equals() method? As we saw in the above example our contract will break. The same thing will happen if we only override hashcode().

So once again just move to contract between equals() and hashcode() methods.

  • If two objects are equals using equals() method, their hashcode must be the same.
  • If two objects having the same hashcode they may or may not be equal using equals() method.

The first point seems ok. The second point may a little bit confusing, It may come into mind how it is possible if two objects having the same hashcode but they will not equal using equals() method. Yes it’s possible let’s see below example.

 

package equalandhashcode;

public class Example1 {
public static void main(String[] args) {
	
	String s1 = "0-42L";
	String s2 = "0-43-";
	
	//both s1 and s2 have same hashcode
	System.out.println("hashcode of s1 :- "+s1.hashCode());
	System.out.println("hashcode of s2 :- "+s2.hashCode());
	
	//s1 and s2 are not equal using equals method
	System.out.println("s1 and s2 using equals() method :- "+s1.equals(s2));
}
}

Output is –

hashcode of s1 :- 45721201
hashcode of s2 :- 45721201
s1 and s2 using equals() method :- false

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

        String s1 = "FB";
        String s2 = "Ea";

        //both s1 and s2 have same hashcode
        System.out.println("hashcode of s1 :- "+s1.hashCode());
        System.out.println("hashcode of s2 :- "+s2.hashCode());

        //s1 and s2 are not equal using equals method
        System.out.println("s1 and s2 using equals() method :- "+s1.equals(s2));
    }
}

Output is –

hashcode of s1 :- 2236
hashcode of s2 :- 2236
s1 and s2 using equals() method :- false


In both examples, both string objects are different but they have the same hashcode.

That’s all about equals() and hashcode() contract in java.

You may like.