【问题标题】:Sets and ConcurrentModificationException [duplicate]集合和 ConcurrentModificationException [重复]
【发布时间】:2014-09-01 22:41:35
【问题描述】:

我每个循环都有一个 Set 类型。

当我遍历这个 Set 时,我会向它添加元素。

 for (Object o: Set) {
    //i do something and add to the set
  }

我不断收到ConcurrentModificationException。但我不知道如何添加到不会导致此异常的Set。我无法为每个不起作用的循环创建一个新的。

谁能指出我正确的方向?

【问题讨论】:

  • @RuchiraGayanRanaweera:据我所知,迭代器允许删除值,但不允许添加
  • 您所说的“我不能为每个不起作用的循环创建一个新的循环”是什么意思 - 究竟什么不起作用,以及以什么方式不起作用?我通常只是建立一个“事后添加的东西”的集合,然后再添加它们......
  • 我的意思是我需要使用完全相同的集合并不断更新它。但我似乎无法弄清楚该怎么做?
  • @RuchiraGayanRanaweera:你想错了。
  • 您尝试做的事情对于标准系列通常是不可能的。但是,如果您可以详细说明,可能会有针对您的问题的特定解决方案。

标签: java loops foreach set


【解决方案1】:

你需要

  • 使用不会触发 ConcurrentModifcationException 的 Set,例如ConcurrentXxxSet
  • 在更改之前获取该集合的副本。

最简单的改变是

for (Object o: set.toArray()) {
    if (condition(o))
       set.add(something);
}

使用泛型可能是一个更简单的解决方案

Set<T> set = 
for(T t: new HashSet<T>(set)) {
   // something which might add to set
}

注意:这将防止它迭代您刚刚添加的元素。 注意 2:使用并发集可能会导致您看到添加的元素,也可能看不到。

如果您确实需要在添加元素时查看元素,则可能需要使用列表,或者也可以使用列表。

List<T> list = new ArrayList<>(set);

for(int i = 0; i < list.size(); i++) {
    T t = list.get(i);

    if (condition)
        // if it is not a duplicate
        if (set.add(something))
            list.add(something);
}

这将使您能够以可靠的方式查看已添加到循环中的元素。注意:需要注意不要创建无限循环并耗尽内存。

另一种方法是使用队列而不是列表。这可能会更好,但我怀疑效率较低。

Queue<T> q = new ConcurrentLinkedQueue<>(set);

for(T t : q) {
    if (condition)
        // if it is not a duplicate
        if (set.add(something))
            q.add(something);
}

【讨论】:

  • 队列效率低多少?我正在处理大量数据,因此我想使用 Set 的原因是什么?
【解决方案2】:

你可以创建一个临时的Set 并将你的元素添加到这个临时集合中,当你完成所有元素的遍历后,将临时集合中的值添加到原始集合中

例子:

Set<Integer> originalSet;
//stuff where you fill your original Set
Set<Integer> tempSet = new Set<Integer>();

for(Integer i : originalSet) {
    tempSet.add(<integerToAdd>);
}
originalSet.addAll(tempSet); 

【讨论】:

  • 但是我如何继续循环遍历 originalSet?我不想让它停止
  • 保持循环是什么意思?它将继续循环遍历您 originalSet 中的所有项目。还是应该循环遍历我添加到 tempList 的项目?
  • 是的,它还需要循环遍历临时列表中的项目并继续直到不再添加项目?与试图让它与集合一起工作的数组列表工作正常
  • 那么,为什么要使用 Set 呢?
  • 效率和速度:)
猜你喜欢
  • 2013-11-12
  • 2016-02-28
  • 2010-12-07
  • 2014-02-10
  • 2013-09-26
  • 1970-01-01
  • 2021-07-01
  • 1970-01-01
  • 2016-12-23
相关资源
最近更新 更多