为什么HashMap快速失败只是因为它提供了迭代其键的方法?

时间:2016-02-18 09:28:15

标签: java hashmap

以下是我所知道的:

  • 快速失败的迭代器会抛出ConcurrentModificationException 如果我尝试在迭代时修改给定元素, 不使用迭代器的方法(如iterator.remove()
  • 不能保证快速失败的迭代器总是会抛出一个CME。
  • 失败安全的迭代器不会抛出CME。

我正在读一本书,在那里我看到了以下句子:

  

HashMap提供了一组密钥,Java应用程序可以迭代   在他们身上。因此,HashMap是快速失败的。

我不理解的部分是它所说的"因此......"。如果有人告诉我HashMap提供了一组密钥,我仍然不知道它是快速失败还是故障安全(仅基于此)。

那么,为什么提供自己的密钥组会使HashMap快速失败?

这两件事之间的联系是什么

3 个答案:

答案 0 :(得分:3)

它实际上是第一个提供HashMap快速失败的信息的句子:

  

HashMap提供了一组密钥,Java应用程序可以迭代它们。

失败安全迭代器迭代原始集合的私有副本,而不是集合本身。因此,对原始集合的任何更改都不会被迭代器注意到,因此它永远不会抛出 CME

由于HashMap提供键组,如上面的引文(而不是副本),因此它是快速失败的。

答案 1 :(得分:1)

作者并没有完成这个想法。
从HashMap的javadocs(https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#keySet()):

"返回此地图中包含的键的Set视图。该集由地图支持,因此对地图的更改将反映在集中,反之亦然。如果在对集合进行迭代时修改了映射(除了通过迭代器自己的删除操作),迭代的结果是未定义的。该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。它不支持add或addAll操作。"

没有表达的想法是使用keySet提供的Set迭代哈希映射(好吧,让我们把它当作迭代地图......)。由于该集合是快速失败的(根据上面的文档),地图也是快速失败的。

请记住,其他方法允许迭代地图(但幸运的是,就我所见,它们也快速失败)。查看https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#entrySet()

答案 2 :(得分:1)

查看包含该确切句子的网页,我认为上下文是HashMapHashTable的比较。如果你看一下Javadoc对HashTable所说的内容,可以让它更清楚:

  

由所有类"集合视图方法"返回的集合的迭代器方法返回的迭代器。 fail-fast :如果在创建迭代器之后的任何时候对Hashtable进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException。因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。 Hashtable的键和元素方法返回的枚举失败快。

因此,有了这个背景,我们可以看出HashMap与HashTable比较的作者试图说HashMap是快速失败的,因为它有一个keySet()方法,它返回失败快速的迭代器正如上面的Javadoc所描述的那样。然而,这给出了不完整的信息,因为它可以暗示,与HashMap不同,HashTable不是快速失败的。实际上,HashTable实现了Map,因此也有keySet()方法,因此它也像HashMap一样具有快速失败的迭代器。该句子的另一个问题是它具有误导性:它不是HashMap的快速失败,而是它返回的迭代器。