2011-08-30 185 views
2

以下樣機代碼在ConcurrentModificationException結束,發生(根據我的理解),由於我正在迭代一套,我正在修改的事實。ConcurrentModificationException,需要澄清

Set<String> data = new HashSet<String>(); 
data.add("a=1"); 
data.add("b=2"); 
data.add("c=3"); 
data.add("d=4"); 

for (String s : data) { 
    data.remove(s); 
} 

但是,爲什麼到了?請幫忙澄清

回答

2

您違反合同迭代器的。從ConcurrentModificationException javadoc

如果單個線程發出的方法調用序列 違反對象的合同,該對象可能拋出此 例外。例如,如果一個線程直接修改集合 而迭代器使用快速迭代器迭代該集合,則迭代器將拋出此異常。

+0

而這樣做的原因是,快速失敗優於「在未來某個未定的時間冒着任意的,非確定性行爲的風險」。 (同一文件) –

+0

@Kublai Khan,感謝您的闡述,但我故意忽略包括那部分,因爲我包含的片段已經足夠。 – mre

+0

因爲這是爲什麼我認爲會有幫助的問題。 -shrug- –

1

你必須使用迭代器從一組

+0

我認爲OP在問爲什麼。 –

2

僅僅是因爲要修改的集合(通過調用data.remove(s)),異常被拋出刪除元素同時遍歷它。 Java集合通常要求在迭代它們的值時不能修改它們。

official documentation

它不是一般允許一個線程修改集合,而另一個線程上進行迭代。一般來說,在這些情況下迭代的結果是不確定的。某些迭代器實現(包括由JRE提供的所有通用集合實現的實現)可能會選擇在檢測到此行爲時拋出此異常。這樣做的迭代器被稱爲快速迭代器,因爲它們快速且乾淨地失敗,而在將來未定的時間冒着任意的,非確定性的行爲冒險。

1

這是因爲編譯器實際上插入了Iterator,然後使用傳統的for循環遍歷元素。如果修改迭代器創建的Collection,則會導致未確定的行爲。爲了防止這種情況,引發ConcurrentModificationException

here參見:

項目7.迭代過程中不要修改該列表。雖然for-each語法不能直接訪問由等價基本for循環使用的迭代器,但可以通過直接調用列表中的其他方法來修改列表。這樣做會導致不確定的程序行爲。特別是,如果編譯器插入的對iterator()的調用返回一個快速失敗的迭代器,則可能會拋出java.util.ConcurrentModificationException運行時異常。但是,這隻能以盡力而爲的方式完成,除非作爲在發生異常時檢測錯誤的手段,否則不能被依賴。

或在Language Specification中的每個循環的部分。