2012-11-09 93 views
3

执行此代码时出现ConcurrentModificationException异常。我无法弄清楚它为什么会发生?Java中的并发修改异常

private void verifyBookingIfAvailable(ArrayList<Integer> list, int id) { 

     Iterator<Integer> iterator = list.iterator(); 
     while (iterator.hasNext()) { 
       int value = iterator.next(); 
       if (value == id) { 
        int index = list.indexOf(id); 

        if (index != -1) { 
         list.remove(index); 
        } 
       } 
     } 
    } 

在此先感谢。

+0

你的代码似乎完全等同于'(list.remove(Integer.valueOf(ID))),同时,除非我失去了'东西... – assylias

+0

@assylias。那么,你不会错过任何东西。你绝对正确。根本不需要重复。很好的抓住:) –

+0

@RohitJain只需确保调用'remove(Object)'而不是'remove(int)'。 – assylias

回答

11

您正在使用list引用本身删除列表中的元素,该引用本身可能会导致ConcurrentModificationException。请注意,这可能有时会起作用,但并非总是如此,并且不能保证完美地工作。

而且,即使您使用Iterator遍历列表,你还是不应该使用list.remove,你应该只使用iterator.remove()删除元素,否则将没有任何区别,无论你用迭代器或用于增强-循环。

因此,请使用iterator.remove()删除元素。

if (index != -1) { 
    iterator.remove(value); 
} 

看到这个职位: - java-efficient-equivalent-to-removing-while-iterating-a-collection的更详细的解释。

+0

tbh,你的回答足够详细:) – PermGenError

+1

@GanGnaMStYleOverFlowErroR ..哈哈:)可能,但这篇文章是非常详细的,可以与我的答案进行比较。 –

+0

谢谢,你的回答非常全面。 – muneikh

1

仅仅因为您正在尝试从ArrayList中删除元素,同时对它们进行迭代。要解决此问题,请使用java.util.concurrent.CopyOnWriteArrayList。希望这可以帮助。

+0

除非在多线程环境中使用列表,否则CopyOnWriteArrayList不是必需的。 – assylias

0

会发生什么情况是ArrayList迭代器不是为了在迭代它时启用修改而设计的。

因此,为了避免更严重的错误从语无伦次数据的到来,它具有当您去除项目内被更新和核对,当你重复的修改次数:

从ArrayList.java:

411  public E remove(int index) { 
412   rangeCheck(index); 
413 
414   modCount++; 
415   E oldValue = elementData(index); 
416 
417   int numMoved = size - index - 1; 
418   if (numMoved > 0) 
419    System.arraycopy(elementData, index+1, elementData, index, 
420        numMoved); 
421   elementData[--size] = null; // Let gc do its work 
422 
423   return oldValue; 
424  } 
    ... 
779 
780   final void checkForComodification() { 
781    if (modCount != expectedModCount) 
782     throw new ConcurrentModificationException(); 
783   } 

正如在javadoc中指定的:

返回的列表迭代器是快速失败的。

为了避免此问题,使用迭代器删除当前元素,而不是直接在列表。迭代器的remove方法确保迭代器保持一致。

0

试试这个

private void verifyBookingIfAvailable(ArrayList<Integer> list, int id) { 

     List<Integer> tempList =new ArrayList<Integer>(); 
    tempList.addAll(list); 

    for(Integer value :tempList) { 

     if (value == 1) { 
      int index = tempList.indexOf(1); 

      if (index != -1) { 

       list.remove(index); 
      } 
     } 
} 
} 

而迭代要删除的对象

+0

wouldnt它仍然抛出异常? – PermGenError

+0

这是你不应该做的修改列表开始。然后是迭代器,应该使用它。但即使在迭代器中,也不能使用'list.remove'。你必须使用'iterator.remove'。所以你的回答没有帮助。因为,你只是向后退一步而不是前进。 –

+0

我做了一些改变,它的工作原理。虽然它可能不是很好的方法 – Suranga