【问题标题】:issue with hashmap getting concurrent modification exceptionhashmap 出现并发修改异常的问题
【发布时间】:2012-09-11 10:48:24
【问题描述】:

我在使用地图并执行一些删除操作时遇到以下错误。如何避免这种情况?

Caused by: java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
    at java.util.HashMap$EntryIterator.next(HashMap.java:834)
    at java.util.HashMap$EntryIterator.next(HashMap.java:832)


   Map<FormField, Object> ItemMap = domainItem.getValues();         
   for (Map.Entry<FormField, Object> ValMap : ItemMap.entrySet()) {         
       List<Field> groupIdList = Mapper.getGroupId(groupFieldId);           
       for (Field field : groupIdList) {
           ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId());
       }
       ItemMap.remove(ValMap.getKey());
   }

【问题讨论】:

    标签: java hashmap concurrentmodification


    【解决方案1】:

    更新:

    使用 Iterator 和 ConcurrentHashMap 来避免这种情况

    以下不会抛出异常

        Map<Integer, String> map = new ConcurrentHashMap<Integer, String>();
        map.put(1, "a");
        map.put(2, "b");
        map.put(3, "c");
        map.put(4, "d");
        for (Iterator<Integer> keys = map.keySet().iterator(); keys.hasNext();) {
            Integer key = keys.next();
            String val = map.get(key);
            map.remove(key);
        }
    

    或在迭代时使用另一个地图,最后将其复制到源

    例如:

        Map<Integer, String> dummy = new HashMap<Integer, String>();
        map.put(1, "a");
        map.put(2, "b");
        map.put(3, "c");
        map.put(4, "d");
        dummy.putAll(map);
        for (Iterator<Integer> keys = dummy.keySet().iterator(); keys.hasNext();) {
            Integer key = keys.next();
            String val = map.get(key);
            map.remove(key);
        }
        System.out.println(map);
    

    【讨论】:

    • 如何避免这种情况我还需要添加数据。
    • ,请解释我如何在上面的 sn-p 中使用迭代器
    • 还可以显示另一个地图和副本 sn-p 示例,因为在我的情况下,地图已经可供我使用
    【解决方案2】:

    Map 按键值对中的键排序。当您在遍历 Map 时添加或删除元素时,程序基本上会丢失它在 Map 中的“位置”。

    要解决此问题,请尝试制作单独的临时转移地图。还有一个名为Iterator 的类可能适合您的需求。

    【讨论】:

    • ,请解释我如何在上面的 sn-p 中使用迭代器
    • Jigar Joshi 在上面的答案中用代码示例解释了它。 =)
    【解决方案3】:

    避免此问题的一种方法是遍历副本。

    for (Map.Entry<FormField, Object> ValMap : 
         new HashMap<FormField, Object>(ItemMap).entrySet()) {
    

    【讨论】:

    • 如果我创建一个副本,那么我可以使用 for (Field field : groupIdList) { ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId()); } ItemMap.remove(ValMap.getKey());
    • 由于您的交互非常复杂,因此无法从您提供的代码中说出来。我会将这段代码移到domainItem 的类中,这样你就可以看到所有的依赖关系。
    • Map ItemMap = domainItem.getValues(); for (Map.Entry ValMap : new HashMap(ItemMap).entrySet()) { List groupIdList = Mapper.getGroupId(groupFieldId); for (Field field : groupIdList) { ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId()); } ItemMap.remove(ValMap.getKey()); }
    • 您需要包含所有调用方法的代码,以防有副作用,这就是为什么建议您将所有代码放在一个地方。我担心的原因是一半的循环似乎不需要在那里,所以一定有一些我看不到的事情正在发生。 ;)
    • 你能不能解释一下其他解决方案,迭代器等等。在我的情况下似乎没有解决
    【解决方案4】:

    不用复制地图也可以,执行这个例子,看看代码:

    public static void main(String[] args)
      {
    
        System.out.println("creating map ...");
    
        Map<String, String> dummyMap = new HashMap<>();
        while (dummyMap.size() < 10)
        { dummyMap.put(String.valueOf(new Random().nextInt()), String.valueOf(new Random().nextInt())); }
    
    
        System.out.println("start, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());
    
    
        System.out.print("going to remove: ");
        for (Iterator<String> keys = dummyMap.keySet().iterator(); keys.hasNext(); )
        {
          final String key = keys.next();
    
          // delete map entries per random
          if(new Random().nextInt(3)>1)
          {
            System.out.print(key+" ");
            keys.remove();
          }
        }
        System.out.print("\n");
    
        System.out.println("done, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());
      }
    

    看看this similar question

    HTH,

    【讨论】:

      猜你喜欢
      • 2013-03-12
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      • 2016-11-19
      • 1970-01-01
      相关资源
      最近更新 更多