2012-11-19 55 views
1

在我的應用程序中,我用一個地圖來存儲POJO對象。根據需求,我需要迭代Map的keySet並刪除不需要修改的對象。併發修改異常與地圖和散列表

求索下面的代碼..

public void remove(Map<String,User> removeUser){ 
    Set<String> keySet = removeUser.keySey(); 
    User user = null; 

    for(String key : keySet){ 
     user = (user) removeUser.get(key); 

     if(!user.isActive()){ 
       removeUser.remove(key); 
     } 
    } 

} 

在這裏,在上面的代碼中,我得到ConcurrentModificationException的,當我嘗試物除去後獲取用戶對象。

誰能告訴我爲什麼發生?

我沒有使用多線程。所以無法理解,它從哪裏產生ConCurrentModification異常。

即使我嘗試使用HashMap和Hashtable,但問題仍然存在。

謝謝, Gunjan。

回答

9

從哪裏產生ConCurrentModification異常。

它來自您嘗試從Map中刪除元素的行,同時遍歷其KeySet

if(!user.isActive()){ 
    removeUser.remove(key); // This is the problem 
} 

你不應該那樣做。如果要修改CollectionMap,請使用iterator


見這個非常不錯的職位 - efficient-equivalent-for-removing-elements-while-iterating-the-collection解釋,同時修改你迭代於集合,可以來的問題。


這裏有一個簡單的代碼說明您可以在這裏使用它: -

Map<String, Integer> map = new HashMap<String, Integer>() { 
     { 
      put("a", 1); 
      put("b", 2); 
      put("c", 3); 
     } 
    }; 

    Iterator<String> iterate = map.keySet().iterator(); 

    while (iterate.hasNext()) { 
     int i = map.get(iterate.next()); 

     if(i > 1) { 
      iterate.remove(); 
     } 
    } 

    System.out.println(map); 

OUTPUT: -

{a=1} 
+0

感謝您的回答感興趣。很好的解釋。我提到了這個鏈接:http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html。在這裏他們已經給出了關於地圖結構變化的ConcurrentModificationException的很好的解釋。 –

+0

@GunjanShah ..當然,這是文檔鏈接。並且對這個東西有一個很好和簡潔的解釋。請繼續參考文檔以瞭解Java中的各種方法。 :) –

+0

啊!我從內存中輸入我的iPhone上。我確定入口已經刪除()!廢話 – Bohemian

2

使用迭代器遍歷您設置和使用iterator.remove(),你不能刪除元素從您的收藏遍歷it.you'd得到ConcurrentModification異常

根源您的異常的是在這裏:

 removeUser.remove(key); 

疊代您這樣設置,使用迭代器。

Iterator<String> itr = keySet .iterator(); 
while(itr.hasNext){ 
    String s = itr.next(); 
    itr.remove(); // to remove the current element. 
} 
4

如果使用ConcurrentHashMap,則不會產生ConcurrentModificationException。

更一般的解決方案是使用迭代器來執行remove()。

public void removeInactiveUsers(Map<String, User> map) { 
    for (Iterator<User> iter = map.values().iterator(); iter.hasNext();) 
     if (!user.isActive()) 
      iter.remove(); 
} 

注意:您不需要keySet(),你只在values()

+0

是的,這也是有效的點。只要使用'values'就足夠了。 +1。 –

+0

@Bohemian我會爭論得到'entrySet()'而不得不調用'getValue()'也比你需要的多。 'Map.Entry.remove()'不存在,所以這是一個作弊;) –

+0

啊!我從內存中輸入我的iPhone上。我確定入口已經刪除()!廢話。 – Bohemian