測試代碼爲:
html
public static void main(String[] args) { List<String> strList = new ArrayList<String>(); strList.add("1"); strList.add("2"); strList.add("3"); strList.add("4"); for(String str:strList){ if(str.equals("4")){ strList.remove(str); } } }
運行後結果以下:
java
跟蹤代碼,拋出異常的地方具體在:函數
public E next() { checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } }
遍歷時返回一個元素以前,會調用checkForComodification()函數進行檢查,該函數實現爲:測試
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
modCount 爲ArrayList修改的次數,expectedModCount 爲指望修改的次數,在刪除第四個元素以前,modCount 和expectedModCount 均爲4(4次add),而調用ArrayList的remove()方法後,modCount 變爲5,但該方法未修改expectedModCount ,其值仍爲4,所以出現上述異常。spa
解決方法爲:單線程環境中,使用 Iterator的remove()方法取代ArrayList的remove()方法,能夠避免ConcurrentModificationException異常。線程
巧合的是,若是要刪除的元素正好是集合中倒數第二個元素,則不會拋出此異常。Iterator遍歷獲取一個元素以前會先調用hasNext()方法來判斷是否還有元素,該方法實現爲:code
public boolean hasNext() { return cursor != size(); }
其中cursor爲遍歷的位置,從0開始,在上面的next()方法中被更新。htm
刪除倒數第二個元素"3"後,已經訪問了3個元素,cursor指向下一個應該訪問的元素位置,即3,而size()也返回3,hasNext()返回false,就不會調用next()方法,所以也不存在ConcurrentModificationException異常。blog
刪除元素"4"後,cursor的值變爲4,而size()返回3,hasNext()返回true,所以調用next()方法時就會拋出ConcurrentModificationException異常。rem
附上一篇資料:
Java ConcurrentModificationException異常緣由和解決方法: