Recently I read through this Developer Works Document.
The document is all about defining hashCode()
and equals()
effectively and correctly, however I am not able to figure out why we need to override these two methods.
How can I take the decision to implement these methods efficiently?
1) The common mistake is shown in the example below.
the green Car is not found
2. Problem caused by hashCode()
The problem is caused by the un-overridden method
hashCode()
. The contract betweenequals()
andhashCode()
is:If two objects have the same hash code, they may or may not be equal.
String class and wrapper classes have different implementation of
equals()
andhashCode()
methods than Object class. equals() method of Object class compares the references of the objects, not the contents. hashCode() method of Object class returns distinct hashcode for every single object whether the contents are same.It leads problem when you use Map collection and the key is of Persistent type, StringBuffer/builder type. Since they don't override equals() and hashCode() unlike String class, equals() will return false when you compare two different objects even though both have same contents. It will make the hashMap storing same content keys. Storing same content keys means it is violating the rule of Map because Map doesnt allow duplicate keys at all. Therefore you override equals() as well as hashCode() methods in your class and provide the implementation(IDE can generate these methods) so that they work same as String's equals() and hashCode() and prevent same content keys.
You have to override hashCode() method along with equals() because equals() work according hashcode.
Moreover overriding hashCode() method along with equals() helps to intact the equals()-hashCode() contract: "If two objects are equal, then they must have the same hash code."
When do you need to write custom implementation for hashCode()?
As we know that internal working of HashMap is on principle of Hashing. There are certain buckets where entrysets get stored. You customize the hashCode() implementation according your requirement so that same category objects can be stored into same index. when you store the values into Map collection using
put(k,v)
method, the internal implementation of put() is:Means, it generates index and the index is generated based on the hashcode of particular key object. So make this method generate hashcode according your requirement because same hashcode entrysets will be stored into same bucket or index.
That's it!
Both the methods are defined in Object class. And both are in its simplest implementation. So when you need you want add some more implementation to these methods then you have override in your class.
For Ex: equals() method in object only checks its equality on the reference. So if you need compare its state as well then you can override that as it is done in String class.
Identity is not equality.
==
test identity.equals(Object obj)
method compares equality test(i.e. we need to tell equality by overriding the method)First we have to understand the use of equals method.
In order to identity differences between two objects we need to override equals method.
For example:
Now hashCode method can understand easily.
hashCode produces integer in order to store object in data structures like HashMap, HashSet.
Assume we have override equals method of
Customer
as above,While working with data structure when we store object in buckets(bucket is a fancy name for folder). If we use built-in hash technique, for above two customers it generates two different hashcode. So we are storing the same identical object in two different places. To avoid this kind of issues we should override the hashCode method also based on the following principles.
hashCode()
to determine the bucket and usesequals()
method to find whether the value is already present in the Bucket. If not it will added else it will be replaced with current valuehashCode()
to find the Entry (bucket) first andequals()
to find the value in Entryif Both are overridden,
Map<A>
if equals is not overridden
Map<A>
If hashCode is not overridden
Map<A>
HashCode Equal Contract
IMHO, it's as per the rule says - If two objects are equal then they should have same hash, i.e., equal objects should produce equal hash values.
Given above, default equals() in Object is == which does comparison on the address, hashCode() returns the address in integer(hash on actual address) which is again distinct for distinct Object.
If you need to use the custom Objects in the Hash based collections, you need to override both equals() and hashCode(), example If I want to maintain the HashSet of the Employee Objects, if I don't use stronger hashCode and equals I may endup overriding the two different Employee Objects, this happen when I use the age as the hashCode(), however I should be using the unique value which can be the Employee ID.