25

如果我在使用 for-each 循环对其进行迭代时修改 Collection,它会给出ConcurrentModificationException. 有什么解决方法吗?

4

4 回答 4

42

使用Iterator#remove.

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

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

于 2011-08-05T15:08:42.783 回答
13

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

例如:

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

for(Item it:items){
    if(remove){
        toRemove.add(it);
    }
}
items.removeAll(toRemove);
于 2011-08-05T15:11:25.093 回答
3

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

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

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

于 2011-08-05T15:14:50.497 回答
2

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

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

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

于 2011-08-05T15:11:56.263 回答