list的數據遍歷時的刪除錯誤及其解決辦法
阿新 • • 發佈:2018-06-30
變化 獨立 ORC -c AI 工作 刪除對象 exc expected
在遍歷list而且特定條件下需要刪除剛剛遍歷完的一個元素時調用的remove(object)會報如下錯誤:主要是因為Iterator 是工作在一個獨立的線程中,並且擁有一個 mutex 鎖。 Iterator 被創建之後會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往後移動的時候就找不到要叠代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。Iterator 在工作的時候是不允許被叠代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前叠代對象的同時維護索引的一致性。是在於foreach方式遍歷元素的時候,是生成iterator,然後使用iterator遍歷。在生成iterator的時候,會保存一個expectedModCount參數,這個是生成iterator的時候List中修改元素的次數。如果你在遍歷過程中刪除元素,List中modCount就會變化,如果這個modCount和exceptedModCount不一致,就會拋出異常,這個是為了安全的考慮。
foreach的remove(Object)的源碼:
- public boolean remove(Object o) {
- if (o == null) {
- for (int index = 0; index < size; index++)
- if (elementData[index] == null) {
- fastRemove(index);
- return true;
- }
- } else {
- for (int index = 0; index < size; index++)
-
if (o.equals(elementData[index])) {
- fastRemove(index);
- return true;
- }
- }
- return false;
-
}
沒有對expectedModCount進行任何修改,導致expectedModCount和modCount不一致,拋出異常。
iterear的remove()源碼
- public void remove() {
- if (lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
- try {
-
ArrayList.this.remove(lastRet);
- cursor = lastRet;
- lastRet = -1;
- expectedModCount = modCount;//處理expectedModCount
- } catch (IndexOutOfBoundsException ex) {
- throw new ConcurrentModificationException();
- }
- } 對expectedModCount重新做了賦值處理的。這樣的話保持expectedModCount = modCount相等,就不會報出錯了。
list的數據遍歷時的刪除錯誤及其解決辦法