HashMap 的迭代器是快速失败的,而 HashTable 的枚举器不是,你到底是啥意思?
Posted
技术标签:
【中文标题】HashMap 的迭代器是快速失败的,而 HashTable 的枚举器不是,你到底是啥意思?【英文标题】:What do you exactly mean by HashMap's iterator is fail-fast and HashTable's enumerator isn't?HashMap 的迭代器是快速失败的,而 HashTable 的枚举器不是,你到底是什么意思? 【发布时间】:2012-02-03 18:37:43 【问题描述】:我正在查找这两个类之间的区别,这一点出现在很多答案中,这个博客是来源: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html
但是我不完全明白。 有人可以详细说明吗?也许举个例子?
感谢您的关注!
【问题讨论】:
【参考方案1】:Fail-fast 意味着当您在迭代时尝试修改内容时,它将失败并抛出 ConcurrentModificationException。
Set keys = hashMap.keySet();
for (Object key : keys)
hashMap.put(someObject, someValue); //it will throw the ConcurrentModificationException here
对于HashTable枚举:
Enumeration keys = hashTable.keys();
while (keys.hasMoreElements())
hashTable.put(someKey, someValue); //this is ok
【讨论】:
Hastable 的迭代器是快速失败的。它的枚举不是。【参考方案2】:最好的方法可能是查看每个类的源代码,由 Open JDK 实现的每个类实现;这样一来,您就可以直接从马嘴里得到答案:-)
除此之外,从本质上讲,“快速失败”意味着如果检测到另一个线程已修改目标 HashMap,则 HashMap 上的迭代器将抛出异常 - 如果您查看 HashMap 的源代码,您将看到这是通过简单地检查预期修改数量的计数器来完成的。如果修改计数与 Iterator 预期的不同,则意味着自上次检查后有人进入并弄乱了 HashMap,因此 Iterator 抛出 ConcurrentModificationException。
“非快速失败”迭代器不会费心检查,并且会愉快地在底层数据结构中执行其业务。因此,您获得了一些灵活性(在这种情况下可能是可疑的灵活性),以换取以后可能会遇到错误;即尝试访问不再存在的值。
与所有fail-fast 策略一样,其理念是越早检测到错误,就越容易从中恢复或调试。
【讨论】:
不只是另一个线程。如果您在迭代地图时修改地图,即使在同一个线程中,也会引发 ConcurrentModification(除非您使用迭代器本身修改地图) 非常真实!我自己犯的一个有时令人困惑的错误:-)【参考方案3】:在调用iterator.next()
时,如果在创建迭代器和调用next()
之间进行了任何修改,则会立即抛出 ConcurrentModificationException。这就是快速失败的意思。
Hashtable 返回的枚举没有这种行为。他们假设您知道自己在做什么,并且如果您在使用其枚举之一对其进行迭代时修改地图,他们的行为(AFAIK)是未定义的。
【讨论】:
以上是关于HashMap 的迭代器是快速失败的,而 HashTable 的枚举器不是,你到底是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章