Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在不引起ConcurrentModificationException的情况下,同时从ArrayList中删除两个对象?_Java_Iterator_Iteration_Concurrentmodification - Fatal编程技术网

Java 在不引起ConcurrentModificationException的情况下,同时从ArrayList中删除两个对象?

Java 在不引起ConcurrentModificationException的情况下,同时从ArrayList中删除两个对象?,java,iterator,iteration,concurrentmodification,Java,Iterator,Iteration,Concurrentmodification,我有以下代码抛出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.hasNe

我有以下代码抛出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
public void foo(ArrayList下注)
迭代器it1=bets.Iterator();
while(it1.hasNext())
下注b1=(下注)下注。下一步()
迭代器it2=bets.Iterator();
while(it2.hasNext())
if(bet1.等于(bet2))
it2.删除();
it1.删除()//此处抛出ConcurrentModificationException
是不是每次调用iterator.next()时只能调用iterator.remove()一次, 在下一次调用iterator.next()之前调用remove两次会导致这种情况吗


任何帮助都将非常感谢。

您需要将所有删除内容收集到
集合中,并在所有迭代完成后删除它们

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);
}
public void foo(ArrayList下注){
Set remove=newhashset();
用于(下注bet1:下注){
用于(下注bet2:下注){
//不一样但相等。
如果(bet1!=bet2&&bet1.equals(bet2)){
删除。添加(bet1);
删除。添加(bet2);
}
}
}
下注。移除所有(移除);
}
是不是每次只能调用iterator.remove()一次 iterator.next()调用,该调用在下一次调用之前删除两次 调用iterator.next()会导致这种情况吗

如果调用
remove()

您得到的是
ConcurrentModificationException
,因为您在同一ArrayList上使用了两个迭代器,并且这两个迭代器都从列表中删除了元素

如果要从列表中删除重复项,请使用@OldCurmudgeon代码或仅此两行:

bets.clear();
bets.addAll(new LinkedHashSet(bets));

当使用remove(inti)(即使用index)或remove(objecto)从Java中的ArrayList中删除元素时,必须在底层数组中填充删除元素所产生的间隙。这是通过将任何后续元素向左移动(从其索引中减去一个)来实现的。为此使用System.arrayCopy方法。这个过程也可以称为洗牌

System.arraycopy(elementData, index+1, elementData, index, numMoved);
这里索引+1是源位置,索引是目标位置。由于位置索引处的元素被删除,所以从索引+1开始的元素被复制到从索引开始的目标


您在循环中执行此操作,Arraylist在给定的瞬间很难保持确定的状态,因此可能会丢失一些更改,为了避免这种情况,我们有Concurrentmodification异常。

虽然这是一个旧答案,但在使用
removeAll
时要小心-它具有指数运行时间(max)取决于要删除的元素的数量。RemoveAll倾向于O(n^2),因为它重复使用contains方法。@user2780757这离O(e^n)还有很长的路要走哦,哈哈,我明白了,对此表示歉意。只要一个人明白了重点,我就没事:-)