Tags

, ,

These days I found this question is quite hot in linkedin’s Java Developer group.Why always override hashcode() if overriding equals()?

In Java, every object has an equals() method which is inherited from the root Object class. However, the default implementation just simply compares the memory addresses of the objects. You can override the default implementation of the equals() method if you wish. But keep in mind If you do that, you MUST also override hashCode(). Otherwise a violation of the general contract for Object.hashCode will occur, which can have unexpected repercussions when your class is in conjunction with all hash-based collections. In the java doc of the Object class, it says “If two objects are equal, then calling the hashCode method on each of the two objects must produce the same integer result.”

Please take a look at the following code:

import java.util.Map;

import java.util.HashMap;
public class Customer{
private long crmID;
private String crmName;

public Customer(long crmID, String crmName) {
super();
this.crmID = crmID;
this.crmName= crmName;
}

public boolean equals(Object obj) {
if (!(obj instanceof Customer))
return false;
if (obj == this)
return true;
return this.crmID == ((Customer) obj).crmID &&
this.crmName == ((Customer) obj).crmName;
}

public static void main(String[] args) {
Map<Customer,String> m = new HashMap<Customer,String>();
m.put(new Customer(12345678L,”Luke Tong”),”Luke Tong”);
System.out.println(m.get(new Customer(12345678L,”Luke Tong”)));
}

}

Compile and run the above code, the output result is

null

Surprise? As you may find the code above does not contain a hashCode() method, thus the system will use the default one which is

public native int hashCode();

What is the return value for this method? A hash code value for this object.You can not expect TWO different objects have the same hash code. This explains why in our sample the result is null (the system can’t find it in memory)

To prove this let us do the following changes in the main method, let us call it version2

public static void main(String[] args) {
Map<Customer,String> m = new HashMap<Customer,String>();
Customer c=new Customer(12345678L,”Luke Tong”);
m.put(c,”Luke Tong”);
System.out.println(m.get(c));
}

The result is

Luke Tong

Instead of creating a new Customer object, in version 2, I stick to the same one. Now the system knows what you are talking about and is able to pick up the right value.

Let’s go back to version 1.

The fix is simple i.e. providing a hashCode() method as follows:

public int hashCode() {
int result = 0;
result = (int)(crmID/12) + crmName.length();
return result;
}

In this way,the equals method will return true, and hashCode will return the same integer value.Then the result is as expected i.e.

Luke Tong

Advertisements