• 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

[hashCode]two meaningfully equal objects in one bucket

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 2066
IntelliJ IDE Clojure Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!~
 
Abimaran Kugathasan
Ranch Hand
Posts: 2066
IntelliJ IDE Clojure Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And, Welcome to JavaRanch!
 
Bartender
Posts: 1561
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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

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

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

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

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
Posts: 2066
IntelliJ IDE Clojure Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Genuine Search Sven Mathijssen!
 
Abimaran Kugathasan
Ranch Hand
Posts: 2066
IntelliJ IDE Clojure Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Have a look on this. Similar topic!
 
Roy Miro
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 1051
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
if you try to change the value after once put in a hashmap then hashmap will be corrupted.
 
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Roy Miro
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok,
thank you all!
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic