I understand why providing same hashcode for two equal (through equals
) objects is important. But is the vice versa true as well, if two objects have same hashcode do they have to be equal? Does the contract still hold? I cannot find an example where this could happen, because if all those attributes that are taking part in equals method are being used to override hashcode method as well then we will always same hashcode of objects that are equal. Please comment.
9 Answers
The purpose of the hashCode
function is allow objects to be quickly partitioned into sets of things that are known to unequal to all items outside their own set. Suppose one has 1,000 items and one divides them into ten roughly-equal-sized sets. One call to hashCode
could quickly identify the item as being not equal to 900 of the items, without having to use equals
on any of those items. Even if one had to use equals
to compare the item to 100 other items, that would still be only 1/10 the cost of comparing it to all 1000 items. In practice, even in a large collection, hashCode
will often eliminate 99.9% or more of the unequal items, leaving at most a handful to be examined.
According to the Javadoc in: http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29
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.
Edit: In the real world two Strings may have the same hash code. For instance, if you want to store all string combinations that contain lowercase English letters (like "aaaaaaaaaa","aaaaaaaaab" and so on) of length 10, you can't assign a unique hash code to each of the 141.167.095.653.376 combinations, since int in Java is 32-bit and, therefore, can have up to 4.294.967.296 distinct values.
As a matter of fact
public int hashCode(){
return 1;
}
Is a valid hashcode implementation...but a terrible one. Will make all your hashtables slow. But yes, you can have two different objects with the same hashcode. But that should not be the general case, a real implementation should give different hashcodes for different values most of the time.
Curiously, NumberFormat is an example of a Java foundation class which violates the recommendation that:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
Here is some code showing this, at least under the version of Java I'm currently running under Mac OS X 10.6.
Numberformat nf = NumberFormat.getNumberInstance();
NumberFormat nf2 = NumberFormat.getNumberInstance();
assert nf != nf2; // passes -- they are different objects
assert !nf.equals(nf2); // passes -- they are not equal
assert nf.hashCode() != nf2.hashCode(); // fails -- same hash code
To prove , if two objects have the same hashCode does not mean that they are equal
Say you have two user defined classes
class Object1{
private final int hashCode = 21;
public int hashCode(){
return hashCode;
}
public boolean equals(Object obj) {
return (this == obj);
}
}
class Object2{
private final int hashCode = 21;
public int hashCode(){
return hashCode;
}
public boolean equals(Object obj) {
return (this == obj);
}
}
Object1 object1 = new Object1();
Object2 object2 = new Object2();
Object1 object3 = new Object1();
if(object1.hashCode() == object2.hashCode()){
// return true, because the hashcodes are same
}
but
if(object1.equals(object3)){
// will fail, because two different objects
}
hashcode() returns a unique integer ID for each object. If an object’s hashcode is not the same as another object’s hashcode, there is no reason to execute the equals() method: you just know the two objects are not the same. On the other hand, if the hashcode is the same, then you must execute the equals() method to determine whether the values and fields are the same.