File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes tricky question about HashMap + equals Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "tricky question about HashMap + equals" Watch "tricky question about HashMap + equals" New topic
Author

tricky question about HashMap + equals

Adolfo Eloy
Ranch Hand

Joined: Mar 21, 2009
Posts: 146

Hi all.

I've had a similar question a minutes ago, but that were about hashCode and buckets mechanism at Hash Maps.
So, by now, I have two codes that when executing the first the equals method is being called, but when executing the second program the equals method are not being called. I could not discover why. Taking a look at the code 1 and code 2 that follows, could someone help me to understand what's going on at this?

code 1[equals method being called]:



code 2[equals method are NOT being called]:


These are the outputs:
output for code 1:
start calling get...
... calling equals ....
true
finish calling get...

output for code 2:
starting calling the get dog...
true
finish calling the get dog...


Thanks in advance for helping!

Adolfo Eloy
Software Developer
OCPJP 6
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40


Hint: Take a look at the hashcodes of the objects being added to the map.


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
Hey Henry,

When i removed the space present between: 'long' and 'board' AND 'aoag' and 'aoara' in the first code, then the equals method is not being called!

But, when i added two words instead of 'rufus' and 'auaus' in the second code as in 'rufus dog' and 'auaus cat', still equals method is not being called! though the hashcode is returning the same length.
There seems to be some issue with the hashcode only, but cant seem to figure out what it could be.

and nice question Adolfo!


OCPJP 95%
Lester Burnham
Rancher

Joined: Oct 14, 2008
Posts: 1337
Read the article I linked to in http://www.coderanch.com/t/518572/java-programmer-SCJP/certification/Collections-Map
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

Rikesh Desai wrote:
There seems to be some issue with the hashcode only, but cant seem to figure out what it could be.


It's quite simple. In the first case, the hash codes are the same. In the second case, the hash codes are different. This means that in the first case, the hashmap needs to call equals to further check. Everything else... the different class names, the different variable names, the different parameters, etc. etc. are just obfuscation details.

Also, the example violates the hashmap contract. The hashmap requires that the keys do not change, or it may not work correctly... but luckily it still works as the hash codes don't change.

Henry
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
Hey Henry,
Thanks for your reply!

But Henry,

i gave a System.out.println statement in both the hashcode() methods.
The hashcode method is called twice in both cases.

In both the calls to hashcode, the value of hashcode remains the same!

in first case hashcode is :
length of "long board" : 10
length of "aoag aoara" : 10

in second case hashcode is :
length of "rufus" : 5
length of "auaus" : 5

so the hashcode is returning the same value so they are being placed in the same bucket.
Then how is it that first is calling the equals method and the second one isnt?
Adolfo Eloy
Ranch Hand

Joined: Mar 21, 2009
Posts: 146


so the hashcode is returning the same value so they are being placed in the same bucket.
Then how is it that first is calling the equals method and the second one isnt?


Rikesh, this is exactly what I'm getting when debugging this code.
Should be some problem regarding the structure of the string?

It's not clear to me yet.

Thanks to all trying to help.
Dieter Quickfend
Bartender

Joined: Aug 06, 2010
Posts: 543
    
    4

It's because mutable state in your equals/hashCode contract upsets the collection comparison, because your hashCode is searching in the wrong bucket.

So use immutable state for your equals/hashCode contract, you won't have that problem.

Also, your equals method is badly implemented. There's a number of problems with it... Look for some more info on the implementation of the equals/hashCode contract


Oracle Certified Professional: Java SE 6 Programmer && Oracle Certified Expert: (JEE 6 Web Component Developer && JEE 6 EJB Developer)
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
Hi Dieter,

Thank you so much for your input.

But in both codes, there is a mutable state.. then why the difference in the calling of equals method?
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
and actually, both the codes are exactly same! just the class names and objects are differing! and ofcourse, the hashcode values..
Lester Burnham
Rancher

Joined: Oct 14, 2008
Posts: 1337
It's all explained in the article I linked to. Twice, by now.
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
Hi Lester,

Yes, I did go through the article that you are referring to. Thank you for referring that.
I did understand that in equals, we shouldnt use mutable - as per the article as it makes the functioning of equals and hashcode inconsistent.

But the point where we are confused is, both the classes have been implemented in the exactly same manner.
then why is there a difference in the calling of equals method? in one class its getting called and in the other it isnt.
Lester Burnham
Rancher

Joined: Oct 14, 2008
Posts: 1337
The code is broken. What is the point of second-guessing the class libraries how they might manifest that fact?
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

I try to explain my best

From HashMap source code




understand? actually Lester said correctly that *The code is broken*
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83

understand? actually Lester said correctly that *The code is broken*


where?? both the codes are broken? if so, why is equals being called in the first case?

as per the hashcode sourcecode that you provided, --> is it cause we are keeping the hashcode value as 5 in the second code is where the code is breaking?

thanks for providing the source code though... but still not able to get this thing clear..
Saifuddin Merchant
Ranch Hand

Joined: Feb 08, 2009
Posts: 605

Ok I'll give you another clue of why it behaves as if the first one is working and second one is not,

First One --



Second One



Notice any difference between the two now?

Like everyone is pointing out, both are broken and its just because of the specific HashCode values, that the equals may be called or not!


Cheers - Sam.
Twisters - The new age Java Quiz || My Blog
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

Rikesh Desai wrote:why is equals being called in the first case?


HashMap get() use hashing - pointing the existing bucket even key object changes, so e.hash==hash success and go to the equals method . to test this , I given the code already


but it is not the case in 2nd scenario.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

Rikesh Desai wrote:
so the hashcode is returning the same value so they are being placed in the same bucket.
Then how is it that first is calling the equals method and the second one isnt?


There are two objects going into the map. You need to compare the hash codes of those two objects -- not the same object being mutated, and hence, violates the contract.


Rikesh Desai wrote:
in first case hashcode is :
String length of "long board" : 10
String length of "aoag aoara" : 10
Integer : 10

in second case hashcode is :
String length of "rufus" : 5
String length of "auaus" : 5
Integer: 10


Notice that in the second case, the two object hash codes are different. Since the codes are different, they are landing into different buckets, and hence, no need to call equals to confirm that they are different.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

Lester Burnham wrote:The code is broken. What is the point of second-guessing the class libraries how they might manifest that fact?


Agreed. The fact that the key mutates violate the contract, and hence, all guarantees are off. However, in this case, even though the contract is violated, the map doesn't seem to be broken -- no duplicates being caused, and the object is still in the correct bucket.

Henry
Rikesh Desai
Ranch Hand

Joined: Jun 02, 2010
Posts: 83
thank you!

have now indeed understood where it was going wrong.
that Integer was the culprit!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: tricky question about HashMap + equals