我有以下代码抛出ConcurrentModificationException。 有人可以解释为什么会这样吗?
public void foo(ArrayList<Bet> bets)
Iterator it1 = bets.iterator();
while(it1.hasNext())
Bet b1 = (Bet) bets.next()
Iterator it2 = bets.iterator();
while(it2.hasNext())
if(bet1.equals(bet2))
it2.remove();
it1.remove(); //ConcurrentModificationException thrown here
是否只能为每个iterator.next()调用调用iterator.remove()一次, 并且在下一次调用iterator.next()之前调用remove两次导致这个?
任何帮助都会非常感谢。
答案 0 :(得分:1)
您需要将所有删除内容收集到Set
中,并在所有迭代完成后将其删除。
public void foo(ArrayList<Bet> bets) {
Set<Bet> remove = new HashSet<Bet>();
for ( Bet bet1 : bets ) {
for ( Bet bet2 : bets ) {
// Not the same but equal.
if ( bet1 != bet2 && bet1.equals(bet2)) {
remove.add(bet1);
remove.add(bet2);
}
}
}
bets.removeAll(remove);
}
答案 1 :(得分:0)
是否只能为每个调用iterator.remove()一次 iterator.next()调用,并在下一次调用之前调用remove 调用iterator.next()会导致这个吗?
如果您在没有remove()
的情况下致电next()
,您将获得IllegalStateException
您将获得ConcurrentModificationException
,因为您在同一个ArrayList上使用了2个迭代器,并且它们都从列表中删除了元素。
如果要从列表中删除重复项,请使用@OldCurmudgeon代码或仅使用以下两行代码:
bets.clear();
bets.addAll(new LinkedHashSet(bets));
答案 2 :(得分:0)
当使用remove(int i)(即使用索引)或remove(Object o)从Java中的ArrayList中删除元素时,必须在底层数组中填充通过删除元素而创建的间隙。这是通过将任何后续元素向左移动(从其索引中减去一个)来完成的。为此使用System.arrayCopy方法。流程也可以称为洗牌。
System.arraycopy(elementData, index+1, elementData, index, numMoved);
此处index + 1是源位置,而index是目标位置。由于位置索引处的元素已删除,因此将从索引+1开始的元素复制到从索引开始的目标。
您正在循环执行此操作,Arraylist在给定的瞬间很难维持确定的状态,因此可能会丢失一些更改,为避免这种情况,我们有Concurrentmodification异常。