Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

com.google.common.collect.Sets.SetView bug or feature?

Hello I've this piece of code:

public static void main(String[] args) {
    Set<Integer> set1 = new HashSet<Integer>();
    Set<Integer> set2 = new HashSet<Integer>();
    set1.add(1);
    set1.add(2);
    set1.add(3);
    set1.add(4);
    set1.add(5);

    set2.add(4);
    set2.add(5);
    set2.add(6);
    set2.add(7);
    set2.add(8);

    SetView<Integer> x = Sets.intersection(set1, set2);
    set1.removeAll(x);
    set2.removeAll(x);
}

and it throws

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:841)
    at java.util.HashMap$KeyIterator.next(HashMap.java:877)
    at com.google.common.collect.Iterators$7.computeNext(Iterators.java:627)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:141)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:136)
    at java.util.AbstractSet.removeAll(AbstractSet.java:142)
    at com.Main2.main(Main2.java:30)

is this a normal? or a small bug...

like image 760
user952887 Avatar asked Dec 13 '11 14:12

user952887


1 Answers

SetView is a view of the intersection of these sets, not a copy. From the Guava docs:

An unmodifiable view of a set which may be backed by other sets; this view will change as the backing sets do.

So, when you call set1.removeAll(x) and pass in the view, you're essentially trying to remove from set1 while looping over part of itself. This is the reason for the ConcurrentModificationException.

To achieve what you're trying to do, have a look at SetView.immutableCopy().

For example:

SetView<Integer> intersectionView = Sets.intersection(set1, set2);
ImmutableSet<Integer> intersectionCopy = intersectionView.immutableCopy();
set1.removeAll(intersectionCopy);
set2.removeAll(intersectionCopy);
like image 148
Paul Bellora Avatar answered Nov 10 '22 00:11

Paul Bellora