2010-11-13 65 views
1

我有一個列表ListIterator<PointF>作爲類字段。我填寫方法grow()。當我嘗試從這個列表中使用迭代器時,我得到ConcurrentModificationExceptionJava:無法更改迭代器列表

ListIterator<ListIterator<PointF>> i = mPoints.listIterator(); 
while (i.hasNext()) { 
    ListIterator<PointF> j = i.next(); 
    if (j.hasNext()) 
     PointF tmp = j.next(); // Exception here 
} 

我不知道爲什麼會發生這種代碼會導致exeption以任何方法除了grow()

+0

請發佈一個簡短但完整的程序來演示問題。 – 2010-11-13 13:23:04

+0

@Jon Skeet問題解決了,我在獲得迭代器後修改了我的列表'mPoints'。 – Heheid 2010-11-13 13:42:26

回答

4

如果底層列表的變化,會拋出ConcurrentModificationException之前獲得的迭代器。所以不要在實例字段中存儲迭代器。

0

我們可以肯定地說,ConcurrentModificationException意味着在調用獲取迭代器後的某個時刻,基礎迭代器已被修改。

這並不總是意味着像多線程中的併發;通過在循環中迭代列表並刪除元素,可以很容易地觸發此異常。所以,如果沒有其他線程可能修改這個,那麼我們可以說當前線程已經修改了迭代器的底層數據結構。

這裏沒有足夠的代碼可以肯定,但是您存儲迭代器的做法有點可疑。您何時將(內部)迭代器添加到mPoints?如果它們引用的集合隨時在迭代器創建後發生變化,它將在調用時拋出此異常。因此,只要將迭代器添加到mPoints集合中,就可以有效地鎖定迭代器的數據結構以進行更改,但代碼根本不會很清楚。

所以我懷疑這是你的問題的根本原因。除非是短期的(通常在單個詞法範圍內,例如單個方法調用),否則出於您看到的原因,存儲迭代器可能是個壞主意。這可能是更好的存儲底層集合自己的參考,然後創建上面的代碼塊中的迭代器,像這樣:

ListIterator<Iterable<PointF>> i = mPoints.listIterator(); 
while (i.hasNext()) { 
    Iterator<PointF> j = i.next().iterator(); 
    if (j.hasNext()) 
     PointF tmp = j.next(); 
} 

然後再精確的解決方案取決於你的方法的總體架構。要記住的主要事項是不要長期存儲迭代器,因爲幾乎不可能使其可靠工作。即使它現在可以正常工作,它也會在代碼的不同部分之間創建一種不可見的依賴關係,而這些依賴關係幾乎總是會被實施什麼應該是微不足道的改變的人所打破。