WeakHashMap类的Javadoc解释了为什么会发生这种情况:
映射不变量不适用于此类。因为垃圾收集器可能随时丢弃键,所以 WeakHashMap 可能表现得好像一个未知线程正在默默地删除条目
此外,根据该 javadoc 中引用的解释,您正在使用的增强型 for 循环在后台生成的迭代器属于快速失败类型。
由此类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对映射进行结构修改,除了通过迭代器自己的删除之外的任何方式方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。
因此,由于以下原因,您的循环可能会引发此异常:
- 垃圾收集器已删除键集中的对象。
- 代码之外的东西向该地图添加了一个对象。
- 循环内部发生了修改。
由于您的意图似乎是处理尚未 GC 的对象,我建议使用如下迭代器:
Iterator<String> it = data.keySet().iterator();
int count = 0;
int maxTries = 3;
while(true) {
try {
while (it.hasNext()) {
String str = it.next();
// do something
}
break;
} catch (ConcurrentModificationException e) {
it = data.keySet().iterator(); // get a new iterator
if (++count == maxTries) throw e;
}
}