如何在没有 ConcurrentModificationException 的情况下使用 for-each 循环进行迭代时修改集合? [复制]

Posted

技术标签:

【中文标题】如何在没有 ConcurrentModificationException 的情况下使用 for-each 循环进行迭代时修改集合? [复制]【英文标题】:How to modify a Collection while iterating using for-each loop without ConcurrentModificationException? [duplicate] 【发布时间】:2011-10-20 23:17:26 【问题描述】:

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

【问题讨论】:

【参考方案1】:

使用Iterator#remove

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

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

【讨论】:

所以我只是创建该集合的迭代器对象,使用 hasNext() 遍历集合并使用您的建议删除?谢谢。我也可以添加元素吗? @aps,不,您不能添加元素。是的,从集合中获取迭代器。 通过 listIterator.next() 和 listIterator.add() 循环添加新元素仅在两个 'listIterator' 是同一个对象时才有效。【参考方案2】:

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

例如:

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

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

items.removeAll(toRemove);

【讨论】:

谢谢。我以前也想过这个。但是我有相当多的集合,所以我必须为我拥有的每个集合创建很多冗余的 toRemove 集合。【参考方案3】:

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

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

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

【讨论】:

您能详细说明一下吗?我现在正在使用 LinkedList 吗?使用 ConcurrentLinkedList 会导致性能下降等任何缺点。为什么它不给出例外?修改是否由列表本身处理? 您需要阅读 javadocs 以了解该类的属性。 (对不起,我看错了类名……)【参考方案4】:

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

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

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

【讨论】:

以上是关于如何在没有 ConcurrentModificationException 的情况下使用 for-each 循环进行迭代时修改集合? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

我如何在没有订单的情况下填充托盘架存储?

如何在没有没有索引的 url 的情况下调用 codeigniter 控制器功能

如何在没有 UITableViewController 的情况下结束 UIRefreshControl

如何在没有 GPU 的情况下运行 tensorflow?

如何在没有'id'列的MySql中获取最后插入的记录?

如何在没有 iMessage 的情况下发送短信