Always Override HashCode() If Overriding Equals()

In Java, equals() is implemented in Object class by default. This method is used to compare two objects. The default implementation just simply compares the memory addresses of the objects. You can override the default implementation of the equals() method defined in java.lang.Object. If you override the equals(), you MUST also override hashCode(). Otherwise, a violation of the general contract for Object.hashCode() will occur, which results unexpected behavior when your class is in conjunction with all hash-based collections.

This is a general contract in java programming that “whenever you override equals(), override hashcode() also”.

  • 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() 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() method, then calling the hashCode() method on each of the two objects must produce distinct integer results.

Consider the following two examples. In the 1st example I have overriden equals() only and in the 2nd one I have implemented equals() and hashCode(), see the differences.

Example 1: (override equals() only)

public class HashCodeSample {

private int id;
private int code;
private String name;
public HashCodeSample(int id, int code, String name) {
super();
this.id = id;
this.code = code;
this.name= name;
}

public boolean equals(Object obj) {
if (!(obj instanceof HashCodeSample))
return false;
if (obj == this)
return true;
return this.id == ((HashCodeSample) obj).id &&
this.code == ((HashCodeSample) obj).code;

}

public static void main(String[] arr) {
Map<HashCodeSample,String> m = new Hashtable<HashCodeSample,String>();
HashCodeSample h1 = new HashCodeSample(1234,8, “Test1?);
HashCodeSample h2 = new HashCodeSample(1234,8, “Test2?);
m.put(h1,”Hashcode Test”);
System.out.println(m.get(h2));
}
}

Compile and run this code and this will return null.

Example 2: (override equals() and hashCode())

public class HashCodeSample {

private int id;
private int code;
private String name;
public HashCodeSample(int id, int code, String name) {
super();
this.id = id;
this.code = code;
this.name= name;
}

public boolean equals(Object obj) {
if (!(obj instanceof HashCodeSample))
return false;
if (obj == this)
return true;
return this.id == ((HashCodeSample) obj).id &&
this.code == ((HashCodeSample) obj).code;

}

public int hashCode() {
int result = 0;
result = (int)(id/5) + code;
return result;
}
public static void main(String[] arr) {
Map<HashCodeSample,String> m = new Hashtable<HashCodeSample,String>();
HashCodeSample h1 = new HashCodeSample(1234,8, “Test1?);
HashCodeSample h2 = new HashCodeSample(1234,8, “Test2?);
m.put(h1,”Hashcode Test”);
System.out.println(m.get(h2));
}
}

Compile and run this code and this will return Hashcode Test

What is wrong in the 1st example? The two instances of HashCodeSample are logically equal according to the class’s equals method. Because the hashCode() method is not overridden, these two instances’ identities are not in common to the default hashCode implementation. Therefore, the Object.hashCode returns two different numbers instead. Such behavior violates “Equal objects must have equal hash codes” rule defined in the hashCode contract.



Leave a Reply

three × 3 =