【问题标题】:Avoiding ConcurrentModificationException while modifying multiple Maps修改多个 Map 时避免 ConcurrentModificationException
【发布时间】:2015-11-04 07:54:53
【问题描述】:

我有一个包含多个 HashMap 的类。这些 HashMap 中的值相同,但键不同。我必须从包含它的所有地图中删除相同的元素。删除这些元素的方法将Collection 作为参数,对其进行迭代并从多个HashMap 中删除元素。 代码如下:

private Map<Position, Place> map1 = new HashMap<Position, Place>();
private Map<String, List<Place>> map2 = new HashMap<String, List<Place>>();
private Map<Category, List<Place>> map3 = new HashMap<Category, List<Place>>();

public void removePlaces2(Collection<Place> places) {
    Iterator<Place> iter = places.iterator();
    while (iter.hasNext()) {
        Place p = iter.next();
        Position pos = p.getPosition();
        String name = p.getName();
        Category cat = p.getCategory();
        map1.remove(pos);
        List<Place> list1 = map2.get(name);
        list1.remove(p);
        if (list1.isEmpty()) {
            map2.remove(name);
        }
        if (cat != null) {
            List<Place> list2 = map3.get(cat);
            list2.remove(p);
        }
        this.remove(p);
        modified = true;
    }
    revalidate();
}

该方法在Place p = iter.next(); 行抛出一个ConcurrentModificationException。 (但不是每次。)我不知道如何避免它。如果我使用iter.remove(p),那只会从方法的参数中删除元素:Collection&lt;Place&gt; places。这不是我想要的。 问题是如何在从多个地图中删除元素时避免此异常? 注意:我不会遍历要从中删除元素的地图。

【问题讨论】:

  • 你将它作为参数传递什么?
  • this.remove(p)方法是做什么的?
  • 我的猜测是 this.remove(p)actually 从您正在迭代的 Collection 中删除了该地点,或者该集合是存储在 map2 或 map3 中的列表之一
  • 可能Collection&lt;Place&gt; placesmap2map3 中的List&lt;Place&gt; 之一
  • 您可以复制places,并在副本上进行迭代。

标签: java collections hashmap iteration concurrentmodification


【解决方案1】:

如果您将 map1、map2 或 map3 作为参数传递给 removePlaces2(),请创建一个副本:

removePlaces2(new LinkedList<Place>(map1.values()));

如果异常仍然存在,请尝试使用线程安全版本的地图:

private Map<Position, Place> map1 = Collections.synchronizedMap(new HashMap<Position, Place>());
private Map<String, List<Place>> map2 = Collections.synchronizedMap(new HashMap<String, List<Place>>());
private Map<Category, List<Place>> map3 = Collections.synchronizedMap(new HashMap<Category, List<Place>>());

【讨论】:

  • 作为参数传递列表的副本似乎有效。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-15
  • 1970-01-01
  • 2011-05-03
  • 2017-05-30
  • 2021-11-23
  • 1970-01-01
  • 2013-05-26
相关资源
最近更新 更多