HashMap不应该是线程安全的,那么如果有人修改了hashMap,为什么迭代器会抛出concurrentmodificationexception
。
ConcurrentHashMap也不会抛出此异常。
Iterator实现对于不同的数据结构是不同的,或者这些数据结构中有某个方法抛出ConcurrentModificationException
答案 0 :(得分:3)
当迭代HashMap
时修改HashMap
的结构(即添加或删除条目)时,迭代器可能会以多种方式失败。
ConcurrentModificationException
异常旨在通过此类修改使任何迭代器快速失败。
这是modCount
字段的用途:
/**
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient int modCount;
此行为并非特定于Map
。在迭代期间修改它们时,Collection
也会抛出此异常。
答案 1 :(得分:3)
不要以为Concurrent
只涉及多线程。
异常意味着在使用修改前创建的迭代器时,对结构进行了结构修改。该修改可能由不同的线程执行,但它可能与执行迭代的线程相同。
以下单线程代码产生CME:
Map<String, String> map = new HashMap<>();
map.put("a", "a");
map.put("b", "b");
for (String k: map.entrySet()) {
map.clear();
}
或者,更清楚地显示循环中的迭代器(两个循环是等效的):
Iterator<String> it = map.entrySet().iterator();
while (it.hasNext()) {
String k = it.next();
map.clear();
}
在it.hasNext()
之后调用 map.clear()
,结果为ConcurrentModificationException
。
答案 2 :(得分:0)
Iterator实现对于不同的数据结构是不同的 这些数据结构中有某种方法抛出 ConcurrentModificationException?
是的, Iterator
类中有不同的Collection
实施。
例如, HashMap
类(内部使用HashIterator
),ConcurrentHashMap
(内部使用KeyIterator
,ValueIterator
等)< / strong>,ArrayList
(使用Iterator
中的AbstractList
)等。
HashMap的迭代器与ConcurrentHashMap的迭代器实现不同。
HashMap的迭代器维护版本号(expectedModCount
)并验证checkForComodification()
,如下所示:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
因此,在迭代过程中,如果修改了基础集合大小(通过添加/删除元素),则Iterator
抛出ConcurrentModificationException
,如上所示。
ConcurrentHashMap
Iterator
实现不执行上述检查的位置,因此它不会抛出ConcurrentModificationException
。您还可以在ConcurrentHashMap
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/By.html#id-java.lang.String-。
他们(ConcurrentHashMaps)不会抛出ConcurrentModificationException。但是,迭代器 设计为一次只能由一个线程使用。
答案 3 :(得分:0)
由于HashMap是一个快速失败的集合(java.util包下的所有集合都快速失败),如果对Hashmap主要进行结构或键的任何修改,则Iterator抛出异常。
我们在Hashmap中有一个变量来计算Map中的修改数量。使用该迭代器可以跟踪对集合进行修改的数量。
transient volatile int modCount;
请阅读以下链接:差异解释得非常好: Java Modcount (ArrayList) 好例子: http://www.journaldev.com/122/java-concurrenthashmap-example-iterator