2017-07-29 119 views
3

看看這個小片的代碼:爲什麼不在這裏引發ConcurrentModificationException?

ArrayList al = new ArrayList(); 
al.add("AA"); 
al.add("AB"); 
al.add("AC"); 
Iterator it = al.iterator(); 
while(it.hasNext()){ 
String s = (String)it.next(); 
if(s.equals("AB")){ 
al.remove(1); 
} 
} 

由於ArrayList中具有快速失敗迭代,並清楚地,這將使得remove()方法不可用的給定的ArrayList不是由固定大小的陣列(),上面的代碼應該拋出ConcurrentModificationException,但是,它沒有。另外,如果我在循環中插入一條打印語句(作爲第一條語句),它將顯示循環不會第三次迭代,並且它會優雅地退出。

我知道這聽起來太傻,但我能想到的虛假的唯一原因是去除元素的發生後的元素已遍歷的迭代器的事實。但是,情況並非如此,因爲modificationCount仍然通過刪除進行修改,因此它必須拋出異常。

只是做

while(it.hasNext()){ 
it.next(); 
al.remove(1); 
} 

也不過拋出ConcurrentModificationException。

任何見解?謝謝!

回答

2

這是因爲該hasNext()方法不檢查modCount

public boolean hasNext() { 
    return cursor != size; 
} 

因此,呼籲remove(1)後,該列表的大小爲2就像光標,hasNext()將返回false。永遠不會調用next()方法,並且不會檢查modCount

如果在迭代之前將第四個元素添加到列表中,則會像第二個示例一樣獲得異常。

+0

喜歡精確,簡短和健康的答案!非常感謝。 –

0

併發修改檢查僅發生在迭代器的next()調用中,但不在hasNext()調用中,如Bubletan's answer中所述。

java documentation for ArrayList明確規定,

快速失敗的迭代器拋出 盡力而爲的基礎上ConcurrentModificationException的。因此,編寫一個程序 是錯誤的,這個程序依賴於這個例外的正確性:迭代器的失敗 - 快速 行爲應該只用於檢測錯誤。

因此,在迭代過程中修改集合是一種錯誤的編程習慣。

+0

盡我所能處理的所有執行過程中,一個非常簡單的流程中的變化仍未被發現,這是否盡力而爲?我曾經相信有一些其他類型的信號處理線程會照顧到修改。從你告訴我的情況來看,如果我在使用迭代器遍歷時刪除最後一個元素,那麼由於缺少next()調用,將不會拋出異常,不是嗎? –

+0

布布爾坦的答案清除了所有。它真的不應該被稱爲盡力而爲的基礎:D謝謝! –

相關問題