Concurrent modification of two `Set` by `retainAll`

huangapple go评论73阅读模式
英文:

Concurrent modification of two Set<String> by retainAll

问题

需要在迭代期间使用 `retainAll` 进行集合修改的方法

假设我有如下代码

```java
set.forEach(it - > {
    set.retainAll(someMapWithSets.get(it))
});

我尝试过使用迭代器的方法:

for (Iterator <String> iterator = set.iterator(); iterator.hasNext();) {
    String value = iterator.next();
    set.retainAll(someMapWithSets.get(value))
}

但是这并不起作用。会抛出 ConcurrentModificationException 异常。

如何正确地做到这一点?

更新。

整个任务如下:

我有一个集合

{A,B,C}

我有一个表示元素是否兼容的集合映射:

A: B,C - (表示 A 与 B、C 兼容,依此类推)
B: A,E,C
C: A,B

我需要有一个集合映射,其中包含所有可能的兼容元素组合:

A,B,C

因此,作为解决方案的一部分,我考虑创建一个仅保留给定集合和选择的元素兼容元素的方法。

 public static Set <String> define(Set <String> elements, String rootElement) {
        Set <String> result = someMapWithElements.get(rootElement);
        result.retainAll(elements);
        result.add(rootElement);
        result.forEach(it - > result.retainAll(someMapWithElements.get(it)))
        return result;
    }

但是显然会出现 ConcurrentModificationException 异常。


<details>
<summary>英文:</summary>

I need some how to modify set during iteration by retainAll

Let&#39;s say I have next code:

```java
set.forEach(it - &gt; {
    set.retainAll(someMapWithSets.get(it))
});

I've tried approach with iterators:

for (Iterator&lt;String&gt; iterator = set.iterator(); iterator.hasNext();) {
    String value = iterator.next();
    set.retainAll(someMapWithSets.get(value))
}

It did not work. ConcurrentModificationException was thrown.

How to do that correctly?

Update.

Whole task is the next: 

I have set

{A,B,C}

And I have map of sets which indicates if elements are compatible:

A: B,C - (means A is compatible with B and C and etc) 
B: A,E,C
C: A,B

I need to have map of sets where all possible combinations of compatible elements are present:

A,B,C

So as I part of solution I thought I could create method that retains only compatible elements for the given set and chosen element.

 public static Set&lt;String&gt; define(Set&lt;String&gt; elements, String rootElement) {
        Set&lt;String&gt; result = someMapWithElements.get(rootElement);
        result.retainAll(elements);
        result.add(rootElement);
        result.forEach(it -&gt; result.retainAll(someMapWithElements.get(it)))
        return result;
    }

But obviously I get ConcurrentModificationException

答案1

得分: 1

你不能在迭代同一对象时使用 retainAll 方法来修改集合。因此,您需要创建一个新的集合(或其他集合),用作迭代变量,例如:

new HashSet(set).forEach(it -> {
    set.retainAll(someMapWithSets.get(it));
});

可以将 HashSet 替换为适当的 TreeSet 或其他集合对象。

如果确实需要在迭代时更改集合,则需要使用迭代器中的 remove 方法。

英文:

You cannot change a set using the retainAll method while iterating over that same object. Therefore you will need to create a new set (or other collection) to use as an iteration variable, like:

new HashSet(set).forEach(it - &gt; {
    set.retainAll(someMapWithSets.get(it))
});

HashSet can be replaced by TreeSet or any other set object that is suitable.

If actually need to change the set while iterating, you will need to use the remove method in Iterator.

huangapple
  • 本文由 发表于 2020年9月30日 00:46:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/64124103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定