[英]Remove two objects at the same time from an ArrayList without causing a ConcurrentModificationException?
I have the following code that is throwing a ConcurrentModificationException.我有以下代码抛出 ConcurrentModificationException。 Can someone please explain why this is happening?
有人可以解释为什么会这样吗?
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
Is it the case that I can only call iterator.remove() once for each iterator.next() call, and that calling remove twice before the next call to iterator.next() is causing this?对于每个 iterator.next() 调用,我只能调用 iterator.remove() 一次,并且在下一次调用 iterator.next() 之前调用 remove 两次会导致这种情况吗?
Any help would be great thanks.任何帮助都会非常感谢。
You need to gather all removals into a Set
and remove them after all iterations are complete.您需要将所有删除收集到一个
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);
}
Is it the case that I can only call iterator.remove() once for each iterator.next() call, and that calling remove twice before the next call to iterator.next() is causing this?
对于每个 iterator.next() 调用,我只能调用 iterator.remove() 一次,并且在下一次调用 iterator.next() 之前调用 remove 两次会导致这种情况吗?
If you call remove()
without next()
you'll get IllegalStateException
如果你在没有
next()
情况next()
调用remove()
next()
你会得到IllegalStateException
You are getting ConcurrentModificationException
because you use 2 iterators on the same ArrayList and both of them removing elements from the list.您收到
ConcurrentModificationException
是因为您在同一个 ArrayList 上使用了 2 个迭代器,并且它们都从列表中删除了元素。
If you want to remove duplicates from the list, use can use @OldCurmudgeon code or just this 2 lines:如果要从列表中删除重复项,可以使用 @OldCurmudgeon 代码或仅使用以下 2 行:
bets.clear();
bets.addAll(new LinkedHashSet(bets));
When elements are removed from an ArrayList in Java using either remove(int i) (ie using index) or remove(Object o), gap created by the removal of an element has to be filled in the underlying array.当使用 remove(int i)(即使用索引)或 remove(Object o) 从 Java 中的 ArrayList 中删除元素时,必须在底层数组中填充因删除元素而产生的间隙。 That is done by Shifting any subsequent elements to the left (subtracts one from their indices).
这是通过将任何后续元素向左移动(从它们的索引中减去一个)来完成的。 System.arrayCopy method is used for that.
System.arrayCopy 方法用于此目的。 Process can also be called as shuffling.
过程也可以称为混洗。
System.arraycopy(elementData, index+1, elementData, index, numMoved);
Here index+1 is the source position and index is the destination position.这里 index+1 是源位置,index 是目标位置。 Since element at the position index is removed so elements starting from index+1 are copied to destination starting from index.
由于位置 index 处的元素被删除,因此从 index+1 开始的元素被复制到从 index 开始的目的地。
You are doing this operation in a loop it becomes difficult for the Arraylist to maintain a definite state at a given instant, and hence some changes may be lost, to avoid this we have Concurrentmodification exception.您在循环中执行此操作,Arraylist 在给定时刻保持确定状态变得困难,因此可能会丢失一些更改,为了避免这种情况,我们有 Concurrentmodification 异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.