wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes [hashCode]two meaningfully equal objects in one bucket Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "[hashCode]two meaningfully equal objects in one bucket" Watch "[hashCode]two meaningfully equal objects in one bucket" New topic
Author

[hashCode]two meaningfully equal objects in one bucket

Roy Miro
Greenhorn

Joined: Aug 29, 2010
Posts: 12
Hello all,

It is my first post on this forum.
I'm preparing for the scjp exam with Kathy Sierra and Bert Bates' book.
Before, i have been reading you for a while.


with this given code:




I get this console output:
UN (hashcode: 2) _ DEUX (hashcode: 4)
map size: 2
UN (hashcode: 2) _ UN (hashcode: 2)
map size: 2
Dolphin 1
Both meaningfully equal


My question is:
after the renaming (both dolphins are named "UN"), both dolphins are in the same "bucket" (thanks to the hashCode method, as you can see their hashcode value is 2) and both are "meaningfully equals" to the dolphin created I passed to map.get(...) to perform the search:

Why does map.get(new Dolphin("UN")) return the dolphin previouly referenced by d1 and why not the one referenced by d2?
(in the console output, i get "Dolphin 1"...) while d1 and d2 succeed the equal test after the renaming?

Thank you for your help and time!
Please don't hesitate to solicit me if something isn't clear.
Abimaran Kugathasan
Ranch Hand

Joined: Nov 04, 2009
Posts: 2066

Roy Miro wrote:
both dolphins are in the same "bucket"


How do you conclude this? HashMap don't allow duplicates. And still your HashMap's size is 2. When you create the HashMap, it will create hash buckets. How do you tell, that, they are in same bucket? They story is different!~


|BSc in Electronic Eng| |SCJP 6.0 91%| |SCWCD 5 92%|
Abimaran Kugathasan
Ranch Hand

Joined: Nov 04, 2009
Posts: 2066

And, Welcome to JavaRanch!
pete stein
Bartender

Joined: Feb 23, 2007
Posts: 1561
You've got a problem with your equals method:

You'll want to compare the name strings via the equals method not via the == operator.
Sven Mathijssen
Greenhorn

Joined: Aug 29, 2010
Posts: 19
pete stein wrote:You've got a problem with your equals method:

You'll want to compare the name strings via the equals method not via the == operator.


Athough I agree with you in always comparing through the equals method, in this case it shouldn't matter because two Strings are compared from the String constant pool, returning true for the compared Strings, right?
Abimaran Kugathasan
Ranch Hand

Joined: Nov 04, 2009
Posts: 2066

Sven Mathijssen wrote:
Athough I agree with you in always comparing through the equals method, in this case it shouldn't matter because two Strings are compared from the String constant pool, returning true for the compared Strings, right?


Exactly, I think, the story is different. There are two hashcode buckets, and those objects are in different buckets. So, even with the == opetator, the HashMap size 2.
pete stein
Bartender

Joined: Feb 23, 2007
Posts: 1561
Sven Mathijssen wrote:
Athough I agree with you in always comparing through the equals method, in this case it shouldn't matter because two Strings are compared from the String constant pool, returning true for the compared Strings, right?


I don't believe that it's guaranteed to be the same String only that it is likely to be the same String object. For instance if the String is created using the new String(...) constructor then it is usually a different object.

The key to the problem here though is that the OP's code corrupts the HashMap as keys are not supposed to be changed once used.
Sven Mathijssen
Greenhorn

Joined: Aug 29, 2010
Posts: 19
Abimaran Kugathasan wrote:
Sven Mathijssen wrote:
Athough I agree with you in always comparing through the equals method, in this case it shouldn't matter because two Strings are compared from the String constant pool, returning true for the compared Strings, right?


Exactly, I think, the story is different. There are two hashcode buckets, and those objects are in different buckets. So, even with the == opetator, the HashMap size 2.


This makes an interesting case. What happens when a key is already in a collection and after a change to the object, the object is equal to another object already used as a key in the Collection.

From [1]:


If an object's hashCode() value can change based on its state, then we must be careful when using such objects as keys in hash-based collections to ensure that we don't allow their state to change when they are being used as hash keys. All hash-based collections assume that an object's hash value does not change while it is in use as a key in the collection. If a key's hash code were to change while it was in a collection, some unpredictable and confusing consequences could follow. This is usually not a problem in practice -- it is not common practice to use a mutable object like a List as a key in a HashMap.


[1] http://www.ibm.com/developerworks/java/library/j-jtp05273.html
Sven Mathijssen
Greenhorn

Joined: Aug 29, 2010
Posts: 19
pete stein wrote:
Sven Mathijssen wrote:
Athough I agree with you in always comparing through the equals method, in this case it shouldn't matter because two Strings are compared from the String constant pool, returning true for the compared Strings, right?


The key to the problem here though is that the OP's code corrupts the HashMap as keys are not supposed to be changed once used.


Ah, there is the 'key' to the real problem ;) You are violating Map's contract here:

From [2]


Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map


[2] http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Map.html
Abimaran Kugathasan
Ranch Hand

Joined: Nov 04, 2009
Posts: 2066

Genuine Search Sven Mathijssen!
Abimaran Kugathasan
Ranch Hand

Joined: Nov 04, 2009
Posts: 2066

Have a look on this. Similar topic!
Roy Miro
Greenhorn

Joined: Aug 29, 2010
Posts: 12
After reading your replies, i conclude that:

1. Once a object is put in a bucket it cannot change for an other bucket even if the object's hashCode change (that's why the map size remains 2 in my example).
2. According to Sven Mathijssen links, although technically possible, a key object isn't due to have its state change. Otherwise, the map behavior isn't predictable.

Please confirm that my comprehension is correct.

Thanks a lot for your answers and impressive reactivity.
Shanky Sohar
Ranch Hand

Joined: Mar 17, 2010
Posts: 1051

if you try to change the value after once put in a hashmap then hashmap will be corrupted.

SCJP6.0,My blog Ranchers from Delhi
Divyeshh Patel
Ranch Hand

Joined: Aug 03, 2010
Posts: 37
Roy Miro wrote:After reading your replies, i conclude that:

1. Once a object is put in a bucket it cannot change for an other bucket even if the object's hashCode change (that's why the map size remains 2 in my example).
2. According to Sven Mathijssen links, although technically possible, a key object isn't due to have its state change. Otherwise, the map behavior isn't predictable.

Please confirm that my comprehension is correct.

Thanks a lot for your answers and impressive reactivity.

Yes Roy, you have understood it correctly.


Cheers,
Divyesh.
Roy Miro
Greenhorn

Joined: Aug 29, 2010
Posts: 12
Ok,
thank you all!
 
 
subject: [hashCode]two meaningfully equal objects in one bucket
 
Similar Threads
Problem with HashMap
HashMap Behavior
comparing two objects
HashMap
hashCode and equals implementation