集和ConcurrentModificationException

时间:2014-07-11 10:21:07

标签: java loops foreach set

我为每个循环设置了一个Set类型。

当我遍历此Set时,我向其添加元素。

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

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

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

你需要

  • 使用不会触发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);
}

答案 1 :(得分:0)

你可以制作一个临时的Set并将你的元素添加到这个临时集中,当你完成对所有元素的删除时,将temp集中的值添加到原始集合

示例:

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);