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

时间:2011-08-05 15:07:03

标签: java collections concurrentmodification

如果我在使用for-each循环迭代它时修改Collection,它会给出ConcurrentModificationException。有没有解决方法?

4 个答案:

答案 0 :(得分:38)

使用Iterator#remove

这是在迭代期间修改集合的唯一安全方法。有关更多信息,请参阅The Collection Interface教程。

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

答案 1 :(得分:10)

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

例如:

List<Item> toRemove = new LinkedList<Item>();

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

答案 2 :(得分:3)

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

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

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

答案 3 :(得分:1)

如果您只想从集合中删除元素,可以使用Iterator而不是Iterable。

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

另一种可能更适合您的用例的替代方案,不是使用for-each而是传统的 - 。