Java 如何在迭代Hashmap时获得ConcurrentModificationException?
我试图在迭代器方法中向hashmap添加一个键值对 但这并没有给我带来Java 如何在迭代Hashmap时获得ConcurrentModificationException?,java,collections,iterator,hashmap,Java,Collections,Iterator,Hashmap,我试图在迭代器方法中向hashmap添加一个键值对 但这并没有给我带来ConcurrentModificationException。为什么? 因为Hashmap是快速失效的 Map<String,String> m = new HashMap<>(); m.put("a", "a"); Iterator<String> i = m.keySet().iterator(); while(i.h
ConcurrentModificationException
。为什么?
因为Hashmap是快速失效的
Map<String,String> m = new HashMap<>();
m.put("a", "a");
Iterator<String> i = m.keySet().iterator();
while(i.hasNext()){
System.out.println(i.next());
m.put("dsad", "asfsdf");
}
Map m=newhashmap();
m、 将(“a”、“a”);
迭代器i=m.keySet().Iterator();
while(i.hasNext()){
System.out.println(i.next());
m、 看跌期权(“dsad”、“asfsdf”);
}
如果这是错误的,如何生成ConcurrentModificationException?
谢谢
更新:刚刚检查过
Map<String,String> m = new HashMap<>();
m.put("a", "a");
m.put("abc", "a");
Iterator<String> i = m.keySet().iterator();
while(i.hasNext()){
System.out.println(i.next());
m.put("dsad", "asfsdf");
}
Map m=newhashmap();
m、 将(“a”、“a”);
m、 卖出(“abc”、“a”);
迭代器i=m.keySet().Iterator();
while(i.hasNext()){
System.out.println(i.next());
m、 看跌期权(“dsad”、“asfsdf”);
}
这给了我一个例外。恰巧,
HashMap
代码执行的并发修改检查无法检测到这种情况。Oracle JDK7中的HashMap
迭代器的hasNext
的代码是:
public final boolean hasNext() {
return next != null;
}
…其中(令人困惑!)表示next
是迭代器类中的私有数据成员(不要与iterator
接口上的next
方法混淆-在我看来,调用该数据成员next
是一个非常糟糕的选择)
注意,它不会检查并发修改。与从迭代器#next
中(间接)调用的此代码相比:
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
…由谁来做检查
下面是代码中发生的情况:
HashMap
hasNext
为true,因此进入循环主体next
获取元素;此时,迭代器会记住其内部数据成员上的下一个元素应该是什么(名称混乱的next
),在这种情况下,由于映射中没有下一个元素,next
数据成员被设置为null
,这意味着迭代已经完成hasNext
,它看到next
数据成员为null
,并返回false
next
)
我以前认为这是一个bug,或者说几乎是一个bug,但这是一个相当模糊的领域,其他人也相当合理地认为它不是。文档没有明确说明迭代器的哪些方法将抛出异常,只是说明它将被抛出。文件还说,它只是在“尽力而为”的基础上抛出的,不能保证
无论你是否认为这是一个bug,在这一点上都不太可能被更改,因为更改它的痛苦(破坏一些可能不应该依赖于此行为的现有代码)远远超过了好处(可能更“正确”)。迭代器可能抛出ConcurrentModificationException,但不能保证会 从HashMap的javadoc: 请注意,无法保证迭代器的快速失败行为 一般来说,不可能作出任何硬性保证 在存在非同步并发修改的情况下。快速失败 迭代器尽最大努力抛出ConcurrentModificationException 基础。因此,编写依赖于 关于其正确性的例外:的fail fast行为 迭代器只能用于检测bug 试试这个:
Map<String,String> m = new HashMap<>();
m.put("a", "a");
Iterator<String> i = m.keySet().iterator();
while(i.hasNext()){
m.remove("a");
System.out.println(i.next());
}
Map m=newhashmap();
m、 将(“a”、“a”);
迭代器i=m.keySet().Iterator();
while(i.hasNext()){
m、 删除(“a”);
System.out.println(i.next());
}
为什么这不是一个bug?@Raj:嗯,我认为这是一个bug。我用一些推理更新了答案,并对您的示例中发生的情况进行了更深入的解释。您的问题是在地图上迭代时调用m.put
。i
是否应转到键dsad
?