I’ve been studying for OCJP (former SCJP) and I came across the following example which uses LinkedHashSet:
public class Test{
int size;
public Test(int s){
this.size = s;
}
@Override
public boolean equals(Object obj) {
return (this.size == ((Test)obj).size);
}
public static void main(String[] args) {
LinkedHashSet<Test> s = new LinkedHashSet<Test>();
s.add(new Test(1));
s.add(new Test(2));
s.add(new Test(1));
System.out.println(s.size());
}
}
Now, the question is what is displayed if :
1) implementation stays as is
2) override of hashCode is inserted in the class Test as follows:
public int hashCode() {return size/5};
Running and compiling the code states that the size of set in the first case is 3, while in the second it is 2.
Why?
In case 1, although equals method is overriden, it is never invoked. Does that mean that add() method does not check for object equality if hashCode method is not overriden?
In case 2, hashCode with the given implementation and the give set of Test objects always returns the same number. How is that different from the default hashCode implementation, and why does it cause equals to be invoked?
If you don’t override
hashCode(), then each of your instances will have hashcode calculated from some pre-defined Hashing algorithm inObjectclass. So, all your instances will possibly have different hashcode values (This is not for sure though). Means, each instance will go into its own bucket.Now, even if you overridden
equals()method make two instances equal based on some attribute, their hashcodes are still different.So, two instances with a different hashcodes, can never be equal. So the size of the set is 3. Since it does not have any duplicate.
But, when you override
hashCode()with following implementation: –It will return same value for same
size. So the instances with same value ofsizewill have same hashcodes and also, since you have compared them inequalsmethod on the basis ofsize, so they will beequaland hence they will be considered duplicate in yourSetand hence will be removed.So,Set.size()is 2.Moral: – You should always override
hashCode()whenever you overrideequals()method, to maintain the general contract between the two methods.General contract between
hashcodeandequalsmethod: –same attributesto calculatehashCodethat you used to compare the two instancesStrongly suggested to read at least once: –
Effective Java -Item#9: Always override hashCode when you override equals