我试图更好地理解hashmap,我研究了代码和可能性。当这来找我时
//HashMap
Map<String, String> myMap = new HashMap<>();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
System.out.println("HashMap before iterator: " + myMap);
for(String key : myMap.keySet()){
if(key.equals("3")) {
myMap.put(key + "new", "new3");
myMap.remove("2");
}
};
for(String key : myMap.keySet()){
if(key.equals("3")) {
myMap.put(key + "new", "new3");
break;
}
};
System.out.println("HashMap after iterator: " + myMap);
输出
HashMap before iterator: {1=1, 2=1, 3=1}
HashMap after iterator: {1=1, 3=1, 3new=new3}
迭代器在hashmap中是快速失败的,那么它如何能够适应这种变化。在此之后,我开始知道有一个计数器可以检查hashmap的大小,并在 next() 中的大小不匹配时抛出异常
我没有得到的是如何打破循环,避免在正确的时刻调用next()来跳过检查。我甚至查看了迭代器HashIterator的代码 当代码命中 break;
为什么这段代码不会抛出错误。
//HashMap
HashMap<String, String> myMap = new HashMap<>();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
System.out.println("HashMap before iterator: "+myMap);
for(String key : myMap.keySet()){
if(key.equals("3"))
myMap.remove("2");
};
System.out.println("HashMap after iterator: " + myMap);
for(String key : myMap.keySet()){
if(key.equals("3"))
myMap.put(key + "new", "new3");
};
System.out.println("HashMap after iterator: " + myMap);
请帮助我更好地理解这一点。
答案 0 :(得分:2)
好吧,HashIterator
检查modCount
中的next()
,但未在hasNext()
中检查:
public final boolean hasNext() {
return next != null;
}
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
由于您在循环的最后一次迭代中对HashMap
进行了结构更改,因此更改后hasNext()
会返回false
并且不会再次调用next()
。因此也不例外。
请注意,增强型for循环创建的迭代器不会意识到您向Entry
添加了额外的Map
这一事实。因此,它不会迭代额外的Entry
。快速失效机制只有在调用迭代器的next()
方法时才能工作,但正如前面所解释的那样,当你在循环的最后一次迭代中进行更改时,这种情况不会发生。 / p>