equals and hashCode contract! in java

www.spiroprojects.com

•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(Object) 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(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
I always has a doubt about contract 2. So, I try o clarify this doubt with an example. Consider a case when two objects are equals but returns difference hashCode. Here is one class with bas hashCode and equals methos. I am specifying this class only for example.

class myclass{
int value;
public myclass(int value){
this.value = value;
}
public String toString(){
return "" + value;
}
public boolean equals(Object obj){
return true;
}
public int hashCode(){
return value;
}

Here we always returns true from equals methos, which says that all the objects are equals. But returns different values of hashCode.
Now create a HashSet and store theese value:-

import java.util.*;
public class test{
public static void main(String args[]){
HashSet set = new HashSet();
myclass myObject1 = new myclass(12);
myclass myObject2 = new myclass(13);
set.add(myObject1);
set.add(myObject2);
System.out.println("HashSet is:"+set);
HashSet set2 = new HashSet();
set2.add("vivek");
set2.add("vivek");
System.out.println("HashSet2 is:"+set2);
}
}

Here is the output:-

C:\DOCUME~1\Vivek>java test
HashSet is:[12, 13]
HashSet2 is:[vivek]

If you see the output you realize that eventough myObject1 and myObject2 are equals they are stored as different in HashSet, which is not the case with “vivek”.
The reason behind this is that, the concept of equality is different in “hash based” collection. Given an object the system store these values in two levels one at bucket and another the values in side the bucket.
When we insert myObject1, system will calculate the hash value by calling hashCode method and this value determine the exact bucket under which this “myObject1” will fall. Just assume that this is mapped to bucket1.
Bucket1 —> myObject1
When we add another value system will first verify if the value is already present. In normal case this will happens by just calling equals method, nut in clase of “hash based colelction” this happens in two steps. First hashCode of myObject2 is determined and this will decide the bucket, next system will search this bucket and calls equals method to check if any duplicate value is present. In this case myObject2 will be mapped to different bucket(in indeal situation this should be mapped to bucket1) and hence system will fail to verify that already an equal object(myObject1) is inserted.
Bucket2 –> myObject2
And hence two duplicate values will be inserted in a set which is wrong.
The concept of equality is different in case of “hash based collection”, two objects are considered equal only of they are equal(pass equals()) and have same hashCode.
The same concept applies with HashTable also. Lets modify the program little bit:-

import java.util.*;
public class test{
public static void main(String args[]){
Hashtable table1 = new Hashtable();
myclass myObject1 = new myclass(12);
myclass myObject2 = new myclass(13);
table1.put(myObject1,"abcde");
table1.put(myObject2,"bcdeff");
System.out.println("Hashtable 1 is:"+table1);
Hashtable table2 = new Hashtable();
table2.put("vivek","abcde");
table2.put("vivek","bcdeff");
System.out.println("Hashtable 2 is:"+table2);
}
}

Here is the output:-

C:\DOCUME~1\mohan>java test
Hashtable 1 is:{13=bcdeff, 12=abcde}
Hashtable 2 is:{vivek=bcdeff}

Same reason as describe above applies here. myObject1 and myObject2 are treated differently eventhough they are equals, which is not the case with String 


Previous
Next Post »