wood burning stoves 2.0*
The moose likes Beginning Java and the fly likes Duplicates in a Set Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Duplicates in a Set" Watch "Duplicates in a Set" New topic
Author

Duplicates in a Set

Yaroslav Ashurin
Greenhorn

Joined: Apr 25, 2008
Posts: 20

Dear All,
I'm missing something. Please consider the situation:

import java.util.*;

class ASet {

public static void main(String[] args) {

Set<Drink> set = new HashSet<Drink>();

Drink one = new Drink("Soda");

Drink two = new Drink("Tonic");

Drink three = new Drink("Vodka");

set.add(one);

set.add(two);

set.add(three);

System.out.println(set); // printed {Soda, Tonic, Vodka}, no problem

one.name = "Vodka";

System.out.println(set); // printed {Tonic, Vodka, Vodka} Duplicates?

} //end main

} //end class

And Drink class overrides equals(), hashCode() and toString() this way:

class Drink {

String name;

public int hashCode() {

return name.hashCode(); // since String overrides the hashCode()

}

public boolean equals(Object drink) {

return name.equals((Drink)drink.name);

}

public String toString() {

return name;

}

}

Question is: how it's possible to have entries in a Set that look identical? Thank you.


SCJP 1.5
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3429
    
  12
Did you read the Javadoc for Set ?
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. A special case of this prohibition is that it is not permissible for a set to contain itself as an element.


Joanne
Yaroslav Ashurin
Greenhorn

Joined: Apr 25, 2008
Posts: 20

Joanne,

sure I read the note in API, and still can't figure out what's going on in the set. When you try to delete all the items one at a time like this:

set.remove(one);
set.remove(two);
set.remove(three);

the set does not get empty, there is kinda "ghoast" element left behind, that is set.size() returns 1, not zero, after removal of all the items. Could you please explain it? Thank you so much.
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3429
    
  12
... The behavior of a set is not specified ...
This means that you cannot rely on what will happen in these circumstances. As you have found, maybe you will be unable to remove all the elements from the Set. This is what happens for the Set implementation that you are using. A different implementation might have removed both elements that matched. Another implementation might remove neither of them. Yet another implementation might do something else.
The point is that you cannot rely on the behaviour and so you should avoid such situations.
Wirianto Djunaidi
Ranch Hand

Joined: Mar 20, 2001
Posts: 210

Yaroslav,

The problem is because you changed the content of Drink after it is already added into the Set. Set only prevent adding duplicate into it, so the check is done when you call add() method.

Since your object one is already in the Set, you can change the name to a duplicate.

And the reason you have ghost data with removal after the changes is because Set use the hashcode to find the object to be removed. Since now you have 2 items with same hashcode, Set only removed 1 of them because it never expected 2 of them.
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3429
    
  12
Originally posted by Wirianto Djunaidi:
... is because Set use the hashcode to find the object to be removed.


HashSet uses the hashcode to find the object to be removed. Other Set implementations may work differently.
Yaroslav Ashurin
Greenhorn

Joined: Apr 25, 2008
Posts: 20

I tried HashSet, TreeSet and LinkedHashSet- all of them lead to the same result: ghost entry after one at a time removal. Only iteration order changes from implementation to implementation. Literally, after removal System.out.print(set) brings {}, nothing in the brakets, and set.size() is allways 1, not zero. Frankly, I'm still not getting it... If Set's behavor is not predictable, how I would give a correct answer at scjp exam if such a question appears?
Anyway, thank you all for helping me to understand.
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3429
    
  12
The correct answer would be - the behaviour of a Set is not specified in these circumstances.

Originally posted by Yaroslav Ashurin:
Only iteration order changes from implementation to implementation.


This is nothing to do with having duplicate elements. A Set iterator returns the elements in no particular order, unless the set is an instance of some class that provides a guarantee.
[ June 30, 2008: Message edited by: Joanne Neal ]
Yaroslav Ashurin
Greenhorn

Joined: Apr 25, 2008
Posts: 20

Done. Thanks.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Duplicates in a Set
 
Similar Threads
Hashset & overriding hashcode()
Why is this HashSet allowing duplicates?
HashSet: Allow Duplicates
Sets (Universal, Subsets, Union)
equal( ) and hashCode( ) Examples