Java 使用迭代器删除条目时的ConcurrentModificationException

Java 使用迭代器删除条目时的ConcurrentModificationException,java,swing,hashmap,concurrentmodification,Java,Swing,Hashmap,Concurrentmodification,我有一段简单的代码,它在映射中循环,检查每个条目的条件,如果条件为真,则对条目执行一个方法。之后,条目将从映射中删除。 要从映射中删除条目,我使用迭代器,以避免ConcurrentModificationException 除非我的代码在it.remove()行抛出异常: 原因:java.util.ConcurrentModificationException 在java.util.HashMap$HashIterator.remove(未知源代码)~[?:1.8.0_161] 在package

我有一段简单的代码,它在映射中循环,检查每个条目的条件,如果条件为真,则对条目执行一个方法。之后,条目将从映射中删除。 要从映射中删除条目,我使用
迭代器
,以避免
ConcurrentModificationException

除非我的代码在
it.remove()行抛出异常:

原因:java.util.ConcurrentModificationException
在java.util.HashMap$HashIterator.remove(未知源代码)~[?:1.8.0_161]
在package.Class.method(Class.java:34)~[Class.Class:?]
经过长时间的搜索,我找不到解决此问题的方法,所有答案都建议使用
Iterator.remove()
方法,但我已经在使用它了。
Map.entrySet()
的文档明确规定,可以使用
Iterator.remove()
方法从集合中删除元素

任何帮助都将不胜感激

我的代码:
Iterator it=map.entrySet().Iterator();
while(it.hasNext()){
Entry en=it.next();
if(en.getValue().shouldRun()){
EventQueue.invokeLater(()->updateSomeGui(en.getKey());//此方法中不会修改映射
en.getValue().run();
it.remove();//第34行
}
}

请使用ConcurrentHashMap代替HashMap,因为您在多个线程中处理对象。HashMap类不是线程安全的,也不允许这样的操作。请参阅下面的链接以了解更多与此相关的信息


让我知道更多信息。

如果您无法将
HashMap
更改为
ConcurrentHashMap
,您可以使用另一种方法处理代码

您可以创建一个条目列表,其中包含要删除的条目,然后对其进行迭代并将其从原始映射中删除

e、 g

    HashMap<String, String> map = new HashMap<>();
    map.put("1", "a1");
    map.put("2", "a2");
    map.put("3", "a3");
    map.put("4", "a4");
    map.put("5", "a5");
    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    List<Map.Entry<String, String>> entries = new ArrayList<>();

    while (iterator.hasNext()) {
        Map.Entry<String, String> next = iterator.next();
        if (next.getKey().equals("2")) {
            /* instead of remove
            iterator.remove();
            */
            entries.add(next);
        }
    }

    for (Map.Entry<String, String> entry: entries) {
        map.remove(entry.getKey());
    }
HashMap map=newhashmap();
地图放置(“1”、“a1”);
地图放置(“2”、“a2”);
地图放置(“3”、“a3”);
地图放置(“4”、“a4”);
地图放置(“5”、“a5”);
迭代器迭代器=map.entrySet().Iterator();
列表项=新的ArrayList();
while(iterator.hasNext()){
Map.Entry next=iterator.next();
if(next.getKey().equals(“2”)){
/*而不是移除
iterator.remove();
*/
条目。添加(下一步);
}
}
对于(Map.Entry:entries){
map.remove(entry.getKey());
}

但是您正在从另一个线程调用
en.getKey
。当然,这不是线程安全的。当您在映射上进行迭代时,是否有其他线程可以从映射中添加或删除条目?@Eran
EventQueue.invokeLater
确实做到了这一点-正如我所说的,如果它能工作,我们并不完全有信心,但是,请查看您是否正在使用ConcurrentHashMap或普通HashMap,如果尚未使用,请使用ConcurrentHashMap…@AKSW
en.getKey()
不会对映射进行变异。通常,我会使用CopyOnWriteArrayList复制数组列表,但这在这种上下文中没有意义,因为不能从另一个线程修改映射。从理论上讲,另一个线程可能从中读取,但这不能解释
ConcurrentModificationException
。然而,这段代码存在于一个相当大的东西系统中,包括一些“黑魔法”asm的东西,所以我认为某种东西设法修改了它。我仍然会接受它,因为它确实解决了我的问题。它不一定是一个完全的修改。。。即使只是在另一个线程中读取,也可能抛出此错误。引用文档“例如,通常不允许一个线程在另一个线程迭代集合时修改集合。”Oracle文档: