Java 为什么即使使用迭代器也会得到ConcurrentModificationException?

Java 为什么即使使用迭代器也会得到ConcurrentModificationException?,java,dictionary,exception,iterator,Java,Dictionary,Exception,Iterator,我有3个服务器和一个客户端发送消息。我实现了一个BFT算法。 所以我有这部分代码 int tam = 0; if (unordered.size() <= maxOrderSize) { tam = unordered.size(); } else { tam = maxOrderSize; } HashMap<String, byte[]> prop = new HashMap<String, b

我有3个服务器和一个客户端发送消息。我实现了一个BFT算法。 所以我有这部分代码

    int tam = 0;

    if (unordered.size() <= maxOrderSize) {
        tam = unordered.size();
    } else {
        tam = maxOrderSize;
    }
    HashMap<String, byte[]> prop = new HashMap<String, byte[]>(tam);

    Iterator<String> it = unordered.keySet().iterator();

    for (int i = 0; i < tam; i++) {
        if (it.hasNext()) {
            String id = it.next();
            prop.put(id, unordered.get(id));
            it.remove();
            unordered.remove(id);

        }
    }
知道为什么会这样吗

EDIT1:我试图删除该行:无序。删除(id)

我犯了一个错误:

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at edu.bft.comm.layer.BatchControl.createOrderMessage(BatchControl.java:120)
at edu.bft.comm.layer.BatchControlTPM.run(BatchControlTPM.java:24)

EDIT2:我还想提一下,当我迭代无序时,可能会添加一些新对象,而新消息来自客户端。

您自己正在修改映射

删除此行:
unordered.Remove(id)

从您的编辑中,您正在修改地图,同时对其进行迭代,这显然是问题所在

发言人说:

集合由映射支持,因此对映射的更改反映在 集合,反之亦然。如果在迭代过程中修改了贴图 正在对集合进行覆盖(除了通过迭代器自己的移除) 操作),迭代的结果未定义


如您所见,HashMap将抛出一个
ConcurrentModificationException

您自己正在修改映射

删除此行:
unordered.Remove(id)

从您的编辑中,您正在修改地图,同时对其进行迭代,这显然是问题所在

发言人说:

集合由映射支持,因此对映射的更改反映在 集合,反之亦然。如果在迭代过程中修改了贴图 正在对集合进行覆盖(除了通过迭代器自己的移除) 操作),迭代的结果未定义


HashMap将抛出一个
ConcurrentModificationException

好的,在Edit2之后,我觉得另一个答案是有意义的

首先:如果你有一个标准的HashMap,默认情况下它不是线程安全的!因此,如果其他线程同时修改该集合,则对该集合进行迭代可能会导致问题。也许添加新项目不会导致异常,也许会

如果您有可能更改无序的
的Map实现,请使用线程安全的方法,例如。如果有人在另一个线程使用迭代器对其元素进行迭代时对其进行修改,则该迭代器不会有任何问题-迭代器有自己的项集合,不会直接干扰原始映射


如果您不能更改实现,您就有麻烦了……

好的,在Edit2之后,我觉得另一个答案是有意义的

首先:如果你有一个标准的HashMap,默认情况下它不是线程安全的!因此,如果其他线程同时修改该集合,则对该集合进行迭代可能会导致问题。也许添加新项目不会导致异常,也许会

如果您有可能更改无序的
的Map实现,请使用线程安全的方法,例如。如果有人在另一个线程使用迭代器对其元素进行迭代时对其进行修改,则该迭代器不会有任何问题-迭代器有自己的项集合,不会直接干扰原始映射

如果无法更改实现,则会遇到麻烦…

这正是所阻止的:

例如,如果线程在使用fail fast迭代器迭代集合时直接修改集合,迭代器将引发此异常

通常,当迭代器进行迭代时,不能修改集合。 请参阅和。

这正是阻止的原因:

例如,如果线程在使用fail fast迭代器迭代集合时直接修改集合,迭代器将引发此异常

通常,当迭代器进行迭代时,不能修改集合。

请参阅和。

好,我删除了该行,然后重新启动了程序。现在它还可以。我会等着看它是否会正常结束。谢谢查看第一篇文章,我用发生的事情更新了它,我的代码运行没有问题。您发布了完整的代码吗?您仍然有“无序。删除(id);”在您的codecheck EDIT1。。我描述了删除该行后发生的情况好的,我删除了该行,然后重新开始我的程序。现在它还可以。我会等着看它是否会正常结束。谢谢查看第一篇文章,我用发生的事情更新了它,我的代码运行没有问题。您发布了完整的代码吗?您仍然有“无序。删除(id);”在您的codecheck EDIT1。。我描述了删除该行后发生的情况整个
for
-循环似乎不必要且错误。
while(it.hasNext(){String id=it.next();…}
不是更有意义吗?是的,它可能应该像Kevin suggets那样是一个while循环。此外,您真正想要的是对
entrySet()进行迭代,而不是对
keySet()进行迭代
。如果使用了错误的迭代器,则需要在
prop.put(…)
中进行集合查找。可能还需要使用entrySet的迭代器,即其
remove()
操作可能会起作用。我会更新我的第一篇博文,检查完整的代码。然后编辑2。Thanks@KevinAnderson不,我不想删除所有对象,只想删除从中指定的特定数量的对象tam@MarcusK.检查此输出我在for循环之前添加了一个打印,在for循环之后添加了一个打印。此输出已删除无序行。删除(id);整个
for
-循环似乎是不必要和错误的。while(it.hasNext(){String id=it.next();…}
是否更有意义?是的,它可能应该像Kevin suggets那样是一个while循环。此外,您真正想要的是对
entrySet()进行迭代,而不是对
键集()进行迭代
。如果使用了错误的迭代器,您需要在
prop.put(…)
中进行集合查找。也许通过使用entrySet的迭代器,其
remove()
操作可能会起作用。我会更新我的第一篇文章,检查完整的代码。然后编辑2。Thanks@KevinAnderson不,我不想删除所有的
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.remove(HashMap.java:1456)
at edu.bft.comm.layer.BatchControl.createOrderMessage(BatchControl.java:123)
at edu.bft.comm.layer.BatchControlTPM.run(BatchControlTPM.java:24)
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at edu.bft.comm.layer.BatchControl.createOrderMessage(BatchControl.java:120)
at edu.bft.comm.layer.BatchControlTPM.run(BatchControlTPM.java:24)