This week's book giveaway is in the OCAJP forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide 1Z0-808 and have Jeanne Boyarsky & Scott Selikoff on-line! See this thread for details.
I have a doubt regarding hashCode() and equals() override.
Why is it important that we override hashcode() if we override equals()?I mean,hashCode() refers to memory address of the object,and two objects can be 'equal' even if they are not at the same memory location?
Please be patient with my ignorance and help me.
If you override the equals(), 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.
You can find more excruciating detail in the Java Language Specification, but suffice it to say that if you override equals(), you most override hashCode() because the
language designers say so
But I am not sure why we need at all to override the equals() and hascode() methods in any class; because if we look into this example:-
Say we have a class which has a String variable as isbn which needs to be set by passing through constructor.
This code segment will display objects are equal even though firstBook and secondBook reference two distinct objects. They are considered equal because the objects compared contain the same value.
By overriding the equals() and hascode() method we do nothing new rather than generating a hashcode which uses all the variables values used in that object. So that if that object is compared with any other object, the hashcode() will be check and if it is found as same then they are decided to be equal.
So, why do we need to bother to override this equals() and hascode(), why just follow the process as shown above for firstBook and secondBook ?
Please help to get the clear reasoning regarding this above example in context with overriding equals() and hascode().
marlajee Borstone wrote:This code segment will display objects are equal even though firstBook and secondBook reference two distinct objects. They are considered equal because the objects compared contain the same value.
That depends on the implementation of class Book. With the following implementation they are not equal:
You have to override equals (and therefore also hashCode) to specify what equality means. In your example you assumed that Book equality means ISBN equality, but you do have to implement that first.
There are very good reasons behind overriding equals() and hashCode() in a custom class.
Try to search some reference on how HashMap and HashSet work with custom objects. This will give you an insight on exactly why (and how) one needs to implement equals() and hashCode() in a custom class, in order to get desired results with Hash-based collection classes. It's always good to know the reasons behind the rules of the language, as opposed to take them on face value. You tend to appreciate them more if you know why those rules were put up in the first place. (For example, why can't an overriding method throw a checked exception not thrown by overriding method?)
As Rob explained, the Book class may contain properties ISBN, Title, Authors etc. Which property should be used for equals() comparison still needs to be implemented within the class, else the 2 objects will not be deemed equal in your example.
have a look at the way hascode has been implemented in Object, the default is to convert the memory address of the object into an int and use that. This means that if you override the equals method only and not hascode, calling hashcode on the 2 objects will return different numbers. If you then put these into a hashed collection you won't be able to retrieve them...
Santosh Kumar Nayak wrote:In that scenario when we are using the hashcode method of the Object class then what is the int value returned from the Hashcode method ?
It's not specified; but the docs say that it will often be a "mangled" version of its memory address or reference.
Simply put: it's not important. The only thing that you need to know is that it will be consistent (and ONLY consistent) with Object.equals(), so if you override equals(), but not hashCode(), you will almost certainly end up with them NOT being consistent with each other.
Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
You need to override both the equals(Object) and hashCode() methods only when you need to store those objects in data structures that uses hashing algorithms for storing data (key-value pairs). The reason for this is so that the hashing algorithm can successfully store and retrieve the location of the object in the structure using the hash-code then uses the equals methods to determine if a match has been found.
To elaborate on this lets use some illustration:
The default hashCode method located in the Object class which all objects in Java inherits returns a unique arbitrary value for every object created. So if we create two custom classes of type Circle we would get something like this for the instances hash-codes:
So from this information it is understood that for data structures that use hash-code values for storing data you will run into trouble when putting values in and getting them back out if we don't override both methods. If you put a Circle object as a key with a radius of 7 in such a structure and that circle object has a hash-code value of 23afde it might be placed at location 3 in the data structure which will be used to locate its associated value. Now if say a few lines later in your code or even worse if your application uses serialization and you close your application to reopen it and retrieve the object stored in the structure it will be impossible. This is because the revived or newly created object will have a new hash-code such as 23aee1 and when you pass that it into the structure to find its associated value the structure will not be able to find the location since 23afde referring to location 3 and 23aee1 probably referring to location 77 are two very distinct address locations even though both circle objects have a radius of 7. To overcome this we override the equals and hashCode methods as follows:
Now that we override both the equals and hashCode methods every object that is equal will have the same hashCode value. Going back to the previous scenario with this new implementation the location of every circle object with a radius of 7 will have the same location (7 * 7 + 2) = 59 pointing at location 3. The structure will now be able to find the value for key by supplying a circle object with a radius of 7. And this is the reason to override the equals and hashCode methods together.
Rico Felix wrote:You need to override both the equals(Object) and hashCode() methods only when you need to store those objects in data structures that uses hashing algorithms for storing data (key-value pairs).
What you say is true; however, when you write a class, you rarely know whether anyone who uses it will want to store it in such a structure, so the usual rule is to assume that they will.
And, given that premise:
If you override equals(), you must override hashCode().
It's also worth remembering that even if you do override equals()/hashCode(), you can still use an IdentityHashMap to store objects by identity.
Also: <nitpick> it's not restricted to data structures that store key-value pairs. HashSet, for example, doesn't. </nitpick>
However, I do like your illustration. Good old Circle.