繁体   English   中英

从 ArrayList 同时删除两个对象而不导致 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM