我想知道Java的迭代器。他們爲什麼設計爲拋出併發修改異常?在C++ STL中,您可以遍歷容器並隨時修改內容,但爲什麼不能在Java中執行?爲什麼Java必須拋出併發修改異常?
編輯:更正的問題。被錯誤地框了。
我想知道Java的迭代器。他們爲什麼設計爲拋出併發修改異常?在C++ STL中,您可以遍歷容器並隨時修改內容,但爲什麼不能在Java中執行?爲什麼Java必須拋出併發修改異常?
編輯:更正的問題。被錯誤地框了。
下面是一個的示例爲什麼迭代器在試圖在迭代它時嘗試修改列表時拋出。
假設您的迭代器是使用索引實現的,如ArrayList
:假設您的迭代器指向List
中的位置3。現在您在位置1
處添加一個元素。迭代器不知道你做了什麼變化,所以它仍然指向位置3,但位置3現在保存了原來位於位置2的元素,因爲所有元素都向下移動了。所以你的迭代器現在將訪問兩個元素!那很糟。
所以規則是當你在迭代它的時候修改一個列表,你必須從迭代器本身這樣做,所以迭代器知道如何保持它的位置與列表的修改同步。如果修改列表而不通過迭代器,則迭代器將拋出ConcurrentModificationException
而不是無聲地變成損壞,例如,不止一次訪問元素。
而是解釋爲什麼它們被設計成這個樣子,我只想讓你在這個小祕密:
如果迭代過程中從列表中刪除,你會得到一個併發異常。 如果您在迭代過程中使用迭代器,則可能由於某些其他原因而獲得併發異常。
像這樣的事情
for(Iterator<?> iter = list.getIterator(); iter.hasNext();)
{
MyClass c = iter.getNext();
if(//i need to remove this instance)
iter.remove(iter);
}
包裹在來電或標記變量作爲volatile
可以幫助您避免併發修改那些將同步對象的訪問,阻止您從多個源訪問它同時。
或使用[COW列表(http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html)
我似乎無法獲得今天怎麼等連接東西的竅門....
,而你可以修改集合迭代它。你只需要用Iterator.remove()來完成。
ConcurrentModificationException例如,如果另一個線程在迭代過程中修改了集合,則可能拋出ConcurrentModificationException。這比未定義的行爲更可取。
Java迭代器沒有線程化。可能存在多個線程,並且迭代器在其中可能表現良好。
它與多線程無關。修改底層集合會使迭代失效。 – Zutty
這個異常不一定只在涉及兩個線程修改對象時發生。 [JAVADOC](http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html) –
而且他們不會做任何事情來阻止併發修改 – greedybuddha