2012-11-09 130 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