I have a question about a section of the K&B book. I checked the errata-section and couldn't find this in the errata-list, so now i am not sure about this is really an erratum or just a wrong thought of myself.
On page 543 (chapter 7) you can find this text in a "Exam Watch" box: When using HashSet or LinkedHashSet, the objects you add to them must override hashCode(). If they don�t override hashCode(), the default Object. hashCode() method will allow multiple objects that you might consider "meaningfully equal" to be added to your "no duplicates allowed" set.
I think that hashCode() in that text, has to be replaced with equals() because: - hashCode() determines to which bucket the object belongs - equals() determines which object is "meaningful equal"
And if you don't override the equals() method of Object, it uses the Object's one and that is just checking if references point to same object, so if you create 2 different objects with same attributes they will have different references, not be equal using equals() method of Object and thus both added to a Set
I think the key point is that assuring uniqueness in a set is a two step process, first using the hashcode, then using the equals method. Assume you want to add an object o to a collection c. I think the semantics of a "c.add(o)" is something like this (loosely speaking):
1) Find the bucket identified by o.hashCode() 2) For all members of the set c in this bucket, check if they are "meaningfully equal" to o (by means of the equals method).
If you don't override hashCode() for the class of o, step 1 above will identify a bucket with only one object, namely o. (distinct objects will have distinct buckets for because hashCode is inherited from Object). According to the hash code contract this means, that all distinct objects in the entire set c may be considered unique and "different" from the o object (because they may all reside in different buckets).
If you override the hashCode method properly, it will identify the proper buckets, where the equals method will be used (step 2 above). Thus ensuring the "no duplicates allowed" condition.
My Foo-class (with override of hashCode and no override of equals) Meaningfully equal = same i-value
The output of this example is what i thought in my initial post: the only condition for adding an object = does it have another reference than the objects already in the set. but set contains meaningfully equal objects.
My new Foo-class (with override of equals and no override of hashCode):
if you run the same program again with the new Foo-class you get the following output:
It's not what i thought in my initial post, because it's exactly the same!!! And the equals method is never invoked, because "the hashCode method defined by class Object does return distinct integers for distinct objects" (from Java API)
If i combine both classes into 1 Foo-class (with override of hashCode AND override of equals), you'll get the output you expect and also the "uniqueness" of a set is guaranteed
Output of program with a Foo-class with both methods overridden:
Conclusion: It's still an erratum in the K&B-book because with an override of hashCode() you can still have "meaningfully equal" objects added to your HashSet. Both methods (hashCode and equals) have to be overriden to obtain the functionality you expect from a set (a collection of unique objects)
Originally posted by Roel De Nijs: On page 543 (chapter 7) you can find this text in a "Exam Watch" box: When using HashSet or LinkedHashSet, the objects you add to them must override hashCode(). If they don�t override hashCode(), the default Object. hashCode() method will allow multiple objects that you might consider "meaningfully equal" to be added to your "no duplicates allowed" set.
I think you misunderstood above quote.
If you don't override hashCode() method, then Object's hashCode() will be called. There could be a chance that two objects which are equal will be added in the same HashSet because there hash codes are different.
When it says "multiple objects which you might consider meaningfully equal" itself tells you that equals(Object) gets overridden otherwise how two different objects can be equal if inherited equals(Object) gets called.
In short, the quote which you have posted is talking about joint contract between equals(Object) and hashCode().
i.e., if two objects are equal, then they must have same hashCode value. If you don't override hashCode(), then they can't have same hashCode value as Object's hashCode() will return different value.