我试图在arraylist中使用foreach循环,但当我使用它时,它会给我错误,但当我使用normal for循环时,它工作得很好,这会是什么问题呢?
代码如下:
for (Pair p2 : R) {
if ((p2.getFirstElm() == p.getSecondElm()) && (p2.getFirstElm() != p2.getSecondElm()))
R.add(new Pair (p.getFirstElm(), p2.getSecondElm()));
else if ((p2.getSecondElm() == p.getFirstElm()) && (p2.getFirstElm() != p2.getSecondElm()))
R.add(new Pair (p2.getFirstElm(), p.getSecondElm()));
// else
// There are no transitive pairs in R.
}这是一个不起作用的循环,下面是一个起作用的:
for (int i = 0; i < R.size(); i++) {
if ((R.get(i).getFirstElm() == p.getSecondElm()) && (R.get(i).getFirstElm() != R.get(i).getSecondElm()))
R.add(new Pair (p.getFirstElm(), R.get(i).getSecondElm()));
else if ((R.get(i).getSecondElm() == p.getFirstElm()) && (R.get(i).getFirstElm() != R.get(i).getSecondElm()))
R.add(new Pair (R.get(i).getFirstElm(), p.getSecondElm()));
//else
// There are no transitive pairs in R.
}在使用foreach循环时,我得到的错误是:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at set.problem.fourth.PoSet.makeTransitive(PoSet.java:145)
at set.problem.fourth.PoSet.addToR(PoSet.java:87)
at set.problem.fourth.PoSetDriver.typicalTesting(PoSetDriver.java:35)
at set.problem.fourth.PoSetDriver.main(PoSetDriver.java:13)发布于 2012-03-21 22:19:16
Java Collection类是快速失效的,这意味着如果在某个线程使用迭代器遍历集合时更改集合,
iterator.next()将抛出ConcurrentModificationException。
这种情况可能出现在多线程和单线程环境中。- www.javacodegeeks.com
您不能在for/each循环中修改List,这是作为实现细节的Iterator的语法糖。只有在直接使用Iterator时才能安全地调用.remove()。
请注意,Iterator.remove是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改基础集合,则行为未指定。- Java Collections Tutorial
在for/each循环中调用.add()会修改内容,幕后使用的Iterator会看到这一点并抛出此异常。
一个更微妙的问题是,你列出的第二种方式,每次你.add()的时候,.size()都会增加,所以你最终会处理你.add()的所有东西,这可能会导致一个无尽的循环,这取决于输入的数据是什么。我不确定这是不是你想要的。
解决方案
我将创建另一个ArrayList并对所有新内容执行.add(),然后在循环之后,在原始ArrayList上使用.addAll()将两个列表合并在一起。这将使你正在尝试做的事情变得清晰,除非你的意图是在添加时处理所有新添加的东西。
2014年解决方案:
始终使用Immutable集合类并构建新的Immutable集合类,而不是试图修改单个共享集合类。这基本上是我2012年的答案所说的,但我想让它更明确。
Guava很好地支持这一点,使用ImmutableList.copyOf()传递数据。
使用Iterables.filter()将内容过滤到新的ImmutableList中,没有共享的可变状态,意味着没有并发问题!
发布于 2012-03-21 22:21:48
发布于 2012-03-21 22:23:33
问题是您在循环的第一行执行R.add()。
在第一种情况下,您打开了一个指向数组列表的迭代器。当您执行add操作,然后尝试再次迭代时,迭代器会注意到您下面的数据结构发生了变化。
在for look的情况下,每次只会得到一个新的元素,没有并发修改的问题,尽管大小会随着添加更多的元素而变化。
要解决这个问题,您可能需要添加到一个临时位置并将其添加到循环之后,或者制作初始数据的副本并添加到原始数据。
https://stackoverflow.com/questions/9806421
复制相似问题