it has nothing to do with threading or concurent modification
Its really a simple test just run this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;
public class Test
{
public static void main(String[] args)
{
TreeSet<MyObject> set1 = new TreeSet<MyObject>(new
Comparator<MyObject>(){
public int compare(MyObject o1, MyObject o2)
{
return o1.aString.compareToIgnoreCase(o2.aString);
}
});
set1.add(new MyObject("johan"));
set1.add(new MyObject("rob"));
HashSet<MyObject> set2 = new HashSet<MyObject>();
set2.add(new MyObject("johan"));
set1.removeAll(set2);
System.err.println("this works: " + set1.size() + " == 1, and
remainng object is " + set1.iterator().next() + " == rob");
// add removed back in
set1.add(new MyObject("johan"));
// increase the size of set2 with some other random others
set2.add(new MyObject("random1"));
set2.add(new MyObject("random2"));
// now size is bigger then set1, call removeall again:
set1.removeAll(set2);
System.err.println("this doesnt work: " + set1.size() + " != 1, so
now both objects stil remain! This is because removeAll isnt overwritten by
TreeSet and AbstractSet walks over the smallest set but then compare
fails");
// same for retainAll that also compares wrong.
set1.retainAll(set2);
System.err.println("set1 is now completely empty, but it should have
1 left: " + set1);
// so both methods should always iterator through the colleciton
they get and do the compare on its self
set1 = new MyFixedTreeSet<MyObject>(new Comparator<MyObject>(){
public int compare(MyObject o1, MyObject o2)
{
return o1.aString.compareToIgnoreCase(o2.aString);
}
});
set1.add(new MyObject("johan"));
set1.add(new MyObject("rob"));
set1.removeAll(set2);
System.err.println("now this works: " + set1.size() + " == 1, and
remainng object is " + set1.iterator().next() + " == rob");
// add removed back in
set1.add(new MyObject("johan"));
set1.retainAll(set2);
System.err.println("set1 is now correct, it has 1 left: " + set1);
}
public static class MyObject
{
private final String aString;
MyObject(String str)
{
aString = str;
}
@Override
public String toString()
{
return aString;
}
}
public static class MyFixedTreeSet<E> extends TreeSet<E>
{
public MyFixedTreeSet(Comparator<? super E> comparator)
{
super(comparator);
}
@Override
public boolean retainAll(Collection<?> c)
{
ArrayList<E> list = new ArrayList<E>();
Iterator<?> e = c.iterator();
while (e.hasNext()) {
Object next = e.next();
if (contains(next)) {
list.add((E)next);
}
}
boolean modified = list.size() < size();
if (modified)
{
clear();
for (E item : list)
{
add(item);
}
}
return modified;
}
@Override
public boolean removeAll(Collection<?> c)
{
boolean modified = false;
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
return modified;
}
}
}
johan
On Wed, Mar 4, 2009 at 15:35, Brill Pappin <[email protected]> wrote:
> if "xxx" is a mutable Set then it should work.
>
> However you have to be careful about how you remove elements from the
> collection you working with, depending on your you do it, you'll get an
> exception about concurrent modification.
>
> - Brill
>
>
> On 3-Mar-09, at 5:44 PM, Johan Compagner wrote:
>
> Is this the same?
>>
>> Set set1 = xxx
>> Collection col1 = xxx;
>>
>> foreach (col in col1)
>> set1.remove(col)
>>
>> or
>>
>> set1.removeAll(col1);
>>
>>
>> ???
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>