• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

tricky question about HashMap + equals

 
Ranch Hand
Posts: 146
Eclipse IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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!
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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

 
Ranch Hand
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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!
 
Rancher
Posts: 1337
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Read the article I linked to in https://coderanch.com/t/518572/java-programmer-SCJP/certification/Collections-Map
 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 146
Eclipse IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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.
 
Bartender
Posts: 543
4
Netbeans IDE Redhat Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Rikesh Desai
Ranch Hand
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
and actually, both the codes are exactly same! just the class names and objects are differing! and ofcourse, the hashcode values..
 
Lester Burnham
Rancher
Posts: 1337
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's all explained in the article I linked to. Twice, by now.
 
Rikesh Desai
Ranch Hand
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1337
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The code is broken. What is the point of second-guessing the class libraries how they might manifest that fact?
 
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I try to explain my best

From HashMap source code




understand? actually Lester said correctly that *The code is broken*
 
Rikesh Desai
Ranch Hand
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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..
 
Ranch Hand
Posts: 608
Firefox Browser Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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!
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thank you!

have now indeed understood where it was going wrong.
that Integer was the culprit!
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic