大佬教程收集整理的这篇文章主要介绍了在哈希图上循环时出现并发修改错误,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我有以下错误:
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1584)
at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1607)
at Server$1.run(Server.java:149)
at java.base/java.lang.Thread.run(Thread.java:832)
for (Session key : sessions.keySet()) {
if (key.getPort2() != port && key.getPort1() != port) { // change later to ip
System.out.println("2nd time init 2 clIEnt");
session.setIp2(ip);
session.setPort2(port);
sessionID++;
sessions.put(session,sessionID);
// reset session
session = null;
}
}
你能解释一下为什么会这样吗?
HashMap
及其 entrySey
、keySet
或 values
方法返回的集合在迭代时不允许更改(插入、删除)。您可以创建一个临时列表来循环,同时仍然更改原始地图:
for (Session key : new ArrayList<>(sessions.keySet())) {
...
sessions.put(session,sessionID);
...
}
您还可以创建一个临时列表来存储要插入的元素(在循环之后)。
不是问题,但不确定那部分是做什么的:
// reset session
session = null;
那种危险 -> NullPointerException
在接下来的迭代中(假设 if
块被执行)
在迭代地图内容的同时修改地图,这是被禁止的。
几乎所有的集合类都有充分的理由禁止这样做。假设您有一个包含
的集合a b c g h i j k l
现在您遍历元素,并在处理元素 k 时插入 d。您是否希望 d 被跳过,因为您已经超出了该位置?如果你在位置 b 并插入一个 m 怎么办?你会期望 m 会被处理吗?或者您是否希望新元素不会被处理,因为它们在您开始迭代时不存在?
如果 Java 允许这样做,人们会抱怨意外的行为。这就是 Java 不允许这样做的原因。与旧的编程语言相比,Java 的主要目标之一是避免意外行为。
要解决此问题,请在开始迭代之前创建第二个临时空地图。然后在您的循环中,您可以将新元素放入该临时地图中。然后最后将它们组合起来:
@H_222_5@map<String,String> tmp=new HashMap<>(); for (Session key : sessions.keySet()) { ... tmp.put(session,sessionID); } sessions.putAll(tmp);
这样就很清楚发生了什么,没有意外的行为。
,java.util.HashMap 不是线程安全的,如果您循环遍历 HashMap 元素,同时如果您尝试修改它,JVM 将通过 ConcurrentModificationException。您可以通过 Iterator 迭代 HashMap 元素,也可以改用 ConcurrentHashMap。
以上是大佬教程为你收集整理的在哈希图上循环时出现并发修改错误全部内容,希望文章能够帮你解决在哈希图上循环时出现并发修改错误所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。