![](/img/trans.png)
[英]Remove Random Item From ArrayList Causing ConcurrentModificationException
[英]Remove two objects at the same time from an ArrayList without causing a ConcurrentModificationException?
我有以下代码抛出 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 两次会导致这种情况吗?
任何帮助都会非常感谢。
您需要将所有删除收集到一个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);
}
对于每个 iterator.next() 调用,我只能调用 iterator.remove() 一次,并且在下一次调用 iterator.next() 之前调用 remove 两次会导致这种情况吗?
如果你在没有next()
情况next()
调用remove()
next()
你会得到IllegalStateException
您收到ConcurrentModificationException
是因为您在同一个 ArrayList 上使用了 2 个迭代器,并且它们都从列表中删除了元素。
如果要从列表中删除重复项,可以使用 @OldCurmudgeon 代码或仅使用以下 2 行:
bets.clear();
bets.addAll(new LinkedHashSet(bets));
当使用 remove(int i)(即使用索引)或 remove(Object o) 从 Java 中的 ArrayList 中删除元素时,必须在底层数组中填充因删除元素而产生的间隙。 这是通过将任何后续元素向左移动(从它们的索引中减去一个)来完成的。 System.arrayCopy 方法用于此目的。 过程也可以称为混洗。
System.arraycopy(elementData, index+1, elementData, index, numMoved);
这里 index+1 是源位置,index 是目标位置。 由于位置 index 处的元素被删除,因此从 index+1 开始的元素被复制到从 index 开始的目的地。
您在循环中执行此操作,Arraylist 在给定时刻保持确定状态变得困难,因此可能会丢失一些更改,为了避免这种情况,我们有 Concurrentmodification 异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.