2

在我的应用程序中,我使用 Map 来存储 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,但问题仍然存在。

4

3 回答 3

10

它从哪里生成 ConCurrentModification 异常。

它来自您Map在迭代其KeySet.

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

你不应该那样做。如果要修改Collectionor Map,请使用iterator.


请参阅这篇非常好的帖子 -高效等效的移除元素同时迭代集合,解释在修改您迭代的集合时可能出现的问题。


这是一个简单的代码,解释了如何在这里使用它:-

    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);

输出: -

{a=1}
于 2012-11-19T11:53:11.670 回答
4

如果您使用 ConcurrentHashMap,它不会产生 ConcurrentModificationException。

更通用的解决方案是使用 Iterator 来执行 remove()。

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

注意:您不需要,keySet()因为您只对values()

于 2012-11-19T11:56:38.553 回答
2

使用迭代器来迭代你的Set和 use iterator.remove(),你不能在迭代它时从你的集合中删除元素。你会得到一个ConcurrentModification 异常

您的异常的根本原因在这里:

        removeUser.remove(key);

使用迭代器像这样迭代你的集合。

Iterator<String> itr = keySet .iterator();
while(itr.hasNext){
   String s = itr.next();
   itr.remove(); // to remove the current element.
 }
于 2012-11-19T11:53:53.960 回答