2013-10-01 82 views
6

我有2 HashMap<Integer,Point3D>對象名稱是positiveCoOrdinate and negativeCoOrdinates如何修復線程「main」中的異常java.util.ConcurrentModificationException

我有以下condition.if它檢查PositiveCoOrdinates滿足該對應點加入到negativeCoOrdinatespositiveCoOrdinates刪除。

HashMap<Integer, Point3d> positiveCoOrdinates=duelList.get(1); 
    HashMap<Integer, Point3d> negativecoOrdinates=duelList.get(2); 
    //condition 
    Set<Integer> set=positiveCoOrdinates.keySet(); 
    for (Integer pointIndex : set) { 
     Point3d coOrdinate=positiveCoOrdinates.get(pointIndex); 
     if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) { 
      negativecoOrdinates.put(pointIndex, coOrdinate); 
      positiveCoOrdinates.remove(pointIndex); 
     } 
    } 

在添加,刪除時,我收到以下錯誤。

Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.HashMap$HashIterator.nextEntry(Unknown Source) 
at java.util.HashMap$KeyIterator.next(Unknown Source) 
at PlaneCoOrdinates.CoordinatesFiltering.Integration(CoordinatesFiltering.java:167) 
at PlaneCoOrdinates.CoordinatesFiltering.main(CoordinatesFiltering.java:179) 

對於我的測試中,我提到裏面If condition.it的工作細System.out.println(coOrdinate.x);聲明。

如果我在If條件內添加2行(上面提到的),它會拋出錯誤。

我該如何解決這個問題。

謝謝。

+0

你可以通過使用'entrySet()' –

回答

11

最簡單的方法是使鍵集的副本:

Set<Integer> set= new HashSet<Integer>(positiveCoOrdinates.keySet()); 

出現該問題,因爲你是對矯正的positiveCoOrdinates,而你使用的是Iterator,通過按鍵進行迭代。

您也可以重構您的代碼,並在條目集上使用迭代器。這將是一個更好的方法。

Set<Entry<Integer, Point3d>> entrySet = positiveCoOrdinates.entrySet(); 

    for (Iterator<Entry<Integer, Point3d>> iterator = entrySet.iterator(); iterator.hasNext();) { 
     Entry<Integer, Point3d> entry = iterator.next(); 
     Point3d coOrdinate = entry.getValue(); 
     if (coOrdinate.x > xMaxValue || coOrdinate.y > yMaxValue 
       || coOrdinate.z > zMaxValue) { 
      Integer pointIndex = entry.getKey(); 
      negativecoOrdinates.put(pointIndex, coOrdinate); 
      iterator.remove(); 
     } 
    } 
+0

來避免查找剛剛獲得的密鑰。 – Woody

+3

或者可以使用'Iterator'。 – SudoRahul

+0

感謝它的工作很好... – Hanumath

0

如果要在運行時修改集合,則需要使用Iterator而不是增強for循環。因爲增強型for循環僅提供只讀功能。以下是Iterator例如:

Iterator<Entity> iterator = collection.Iterator(); 
while(iterator.hasNext()){ 
    //DO Your Stuff 
    iterator.remove(); // this function call remove the element from collection at run time 
} 
2

您可以使用增強for-each循環時,從集合迭代不remove()for-each循環隱式使用Iterator<Integer>。該JavaDoc明確指出

的迭代器由所有此類的返回「collection視圖 方法」是快速失敗的:如果地圖在任何 時間從結構上修改創建迭代器之後,以任何方式,除了通過 迭代器自己的remove()方法,迭代器將拋出一個 ConcurrentModificationException。因此,面對併發的修改,迭代器很快並且乾淨地失敗,而不是冒着在將來確定的時間 處的任意的,不確定的行爲冒險。

for-each循環在內部創建一個迭代器並使用它來遍歷集合。然後你改變集合的結構......迭代器必須失敗。問題是你沒有訪問迭代器的方法,所以你必須明確地使用Iterator<Integer>。生成的遍歷字節碼將是相同的,唯一的區別是您可以在列表中移除元素。

Set<Integer> set = positiveCoOrdinates.keySet(); 
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext();) { 
    Integer pointIndex = iterator.next(); 
    Point3d coOrdinate = positiveCoOrdinates.get(pointIndex); 
    if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) { 
     negativecoOrdinates.put(pointIndex, coOrdinate); 
     iterator.remove(pointIndex); // this line changed! 
    } 
} 

如果你不熟悉迭代器和它們的功能,請參閱the Oracle tutorial on Collections

Iterator是一個對象,使您可以通過 集合遍歷並刪除元素有選擇地收集,如果需要 。您通過調用iterator() 方法獲得集合的Iterator

請注意,Iterator.remove()是在迭代期間修改 集合的唯一安全方式;如果 底層集合在迭代 正在進行時以任何其他方式修改,則行爲未指定。

使用Iterator代替for-each結構的,當你需要:

  • 刪除當前元素。 for-each構造隱藏迭代器,因此您不能調用remove()。因此,for-each 構造不適用於過濾。
0

正如有人所指出的勒之所以這樣很常見的問題是併發修改的集合,同時它正被另一個讀取。

您可以使用ConcurrentHashMap或集合像CopyOnWriteArrayLit,但要注意這些方法可能會有點expensive和簡單的換編寫代碼,以消除同一個集合的閱讀,同時在迭代將解決此類問題。

相關問題