关于java:如何在没有ConcurrentModificationException的情况下使用for-each循环迭代时修改Collection?

How to modify a Collection while iterating using for-each loop without ConcurrentModificationException?

本问题已经有最佳答案,请猛点这里访问。

如果我在对集合进行迭代时使用for each循环修改它,它会给出ConcurrentModificationException。有什么解决办法吗?


使用Iterator#remove

这是在迭代期间修改集合的唯一安全方法。有关详细信息,请参见集合界面教程。

如果您还需要在迭代时添加元素的能力,请使用ListIterator


解决方法之一是保存更改并在循环后添加/删除它们。

例如:

1
2
3
4
5
6
7
8
List<Item> toRemove = new LinkedList<Item>();

for(Item it:items){
    if(remove){
        toRemove.add(it);
    }
}
items.removeAll(toRemove);


第二个解决方法是使用迭代器不会给出异常的集合类。例如ConcurrentLinkedQueueConcurrentHashMap等。

这些方法通过为迭代器提供更弱的一致性模型来避免抛出异常。(当然,您需要了解这些模型,并决定它们是否适合您的应用。)

它们通常比非并发集合慢一点,但如果存在重大争用,则比同步集合包装器快。


如果只想从集合中移除元素,可以使用迭代器而不是ITerable。

否则,您可以做的不是迭代原始集合,而是首先复制列表。例如,如果您的集合是一个列表,那么您可以创建一个新的ArrayList(Originalist),并对其进行迭代。应该对原始列表进行修改。

另一种可能更适合您的用例的选择是不为每一个使用,而是为-使用传统的。