如何在没有 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】:第二种解决方法是使用一个集合类,它的迭代器不会给出异常。比如ConcurrentLinkedQueue
、ConcurrentHashMap
等等。
这些通过为迭代器提供较弱的一致性模型来避免引发异常的需要。 (当然,您需要了解这些模型,并确定它们是否适合您的应用程序。)
它们通常比非并发集合慢一点,但如果存在严重争用,它们比同步集合包装器快。
【讨论】:
您能详细说明一下吗?我现在正在使用 LinkedList 吗?使用 ConcurrentLinkedList 会导致性能下降等任何缺点。为什么它不给出例外?修改是否由列表本身处理? 您需要阅读 javadocs 以了解该类的属性。 (对不起,我看错了类名……)【参考方案4】:如果你只是想从集合中移除元素,你可以使用 Iterator 而不是 Iterable。
否则,您可以做的不是迭代原始集合,而是首先制作列表的副本。例如,如果您的集合是一个列表,那么您可以创建一个新的 ArrayList(originList) 并对其进行迭代。应该对原始列表进行修改。
另一种可能更适合您的用例的替代方法不是使用 for-each,而是使用传统的 for-。
【讨论】:
以上是关于如何在没有 ConcurrentModificationException 的情况下使用 for-each 循环进行迭代时修改集合? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有没有索引的 url 的情况下调用 codeigniter 控制器功能