以下是我所知道的:
ConcurrentModificationException
如果我尝试在迭代时修改给定元素,
不使用迭代器的方法(如iterator.remove()
)我正在读一本书,在那里我看到了以下句子:
HashMap提供了一组密钥,Java应用程序可以迭代 在他们身上。因此,HashMap是快速失败的。
我不理解的部分是它所说的"因此......"。如果有人告诉我HashMap提供了一组密钥,我仍然不知道它是快速失败还是故障安全(仅基于此)。
那么,为什么提供自己的密钥组会使HashMap快速失败?
这两件事之间的联系是什么?
答案 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)
查看包含该确切句子的网页,我认为上下文是HashMap
与HashTable
的比较。如果你看一下Javadoc对HashTable
所说的内容,可以让它更清楚:
由所有类"集合视图方法"返回的集合的迭代器方法返回的迭代器。 fail-fast :如果在创建迭代器之后的任何时候对Hashtable进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException。因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。 Hashtable的键和元素方法返回的枚举不失败快。
因此,有了这个背景,我们可以看出HashMap与HashTable比较的作者试图说HashMap是快速失败的,因为它有一个keySet()
方法,它返回失败快速的迭代器正如上面的Javadoc所描述的那样。然而,这给出了不完整的信息,因为它可以暗示,与HashMap不同,HashTable不是快速失败的。实际上,HashTable实现了Map
,因此也有keySet()
方法,因此它也像HashMap一样具有快速失败的迭代器。该句子的另一个问题是它具有误导性:它不是HashMap的快速失败,而是它返回的迭代器。