Fail-Safe Iterator vs Fail-Fast Iterator – 失败安全迭代器与失败快速迭代器对比

最后修改: 2017年 12月 26日

1. Introduction


In this article, we’ll introduce the concept of Fail-Fast and Fail-Safe Iterators.


Fail-Fast systems abort operation as-fast-as-possible exposing failures immediately and stopping the whole operation.


Whereas, Fail-Safe systems don’t abort an operation in the case of a failure. Such systems try to avoid raising failures as much as possible.


2. Fail-Fast Iterators


Fail-fast iterators in Java don’t play along when the underlying collection gets modified.


Collections maintain an internal counter called modCount. Each time an item is added or removed from the Collection, this counter gets incremented.


When iterating, on each next() call, the current value of modCount gets compared with the initial value. If there’s a mismatch, it throws ConcurrentModificationException which aborts the entire operation.


Default iterators for Collections from java.util package such as ArrayList, HashMap, etc. are Fail-Fast.


ArrayList<Integer> numbers = // ...

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number =;

In the code snippet above, the ConcurrentModificationException gets thrown at the beginning of a next iteration cycle after the modification was performed.


The Fail-Fast behavior isn’t guaranteed to happen in all scenarios as it’s impossible to predict behavior in case of concurrent modifications. These iterators throw ConcurrentModificationException on a best effort basis.


If during iteration over a Collection, an item is removed using Iterator‘s remove() method, that’s entirely safe and doesn’t throw an exception.


However, if the Collection‘s remove() method is used for removing an element, it throws an exception:


ArrayList<Integer> numbers = // ...

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    if ( == 30) {
        iterator.remove(); // ok!

iterator = numbers.iterator();
while (iterator.hasNext()) {
    if ( == 40) {
        numbers.remove(2); // exception

3. Fail-Safe Iterators


Fail-Safe iterators favor lack of failures over the inconvenience of exception handling.


Those iterators create a clone of the actual Collection and iterate over it. If any modification happens after the iterator is created, the copy still remains untouched. Hence, these Iterators continue looping over the Collection even if it’s modified.


However, it’s important to remember that there’s no such thing as a truly Fail-Safe iterator. The correct term is Weakly Consistent.


That means, if a Collection is modified while being iterated over, what the Iterator sees is weakly guaranteed. This behavior may be different for different Collections and is documented in Javadocs of each such Collection.

这意味着,如果 Collection在被迭代时被修改,Iterator看到的是弱保证。这种行为对于不同的Collection可能是不同的,并且在每个这样的Collection的Javadocs中都有记录。

The Fail-Safe Iterators have a few disadvantages, though. One disadvantage is that the Iterator isn’t guaranteed to return updated data from the Collection, as it’s working on the clone instead of the actual Collection.

不过,Fail-Safe Iterators有一些缺点。一个缺点是,Iterator不能保证从Collection返回更新的数据,因为它是在克隆上工作,而不是在实际的Collection上工作。

Another disadvantage is the overhead of creating a copy of the Collection, both regarding time and memory.


Iterators on Collections from java.util.concurrent package such as ConcurrentHashMap, CopyOnWriteArrayList, etc. are Fail-Safe in nature.


ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.put("First", 10);
map.put("Second", 20);
map.put("Third", 30);
map.put("Fourth", 40);

Iterator<String> iterator = map.keySet().iterator();

while (iterator.hasNext()) {
    String key =;
    map.put("Fifth", 50);

In the code snippet above, we’re using Fail-Safe Iterator. Hence, even though a new element is added to the Collection during the iteration, it doesn’t throw an exception.

在上面的代码片段中,我们使用的是Fail-Safe Iterator。因此,即使在迭代过程中,一个新的元素被添加到Collection中,它也不会抛出一个异常。

The default iterator for the ConcurrentHashMap is weakly consistent. This means that this Iterator can tolerate concurrent modification, traverses elements as they existed when Iterator was constructed and may (but isn’t guaranteed to) reflect modifications to the Collection after the construction of the Iterator.


Hence, in the code snippet above, the iteration loops five times, which means it does detect the newly added element to the Collection.


4. Conclusion


In this tutorial, we’ve seen what Fail-Safe and Fail-Fast Iterators mean and how these are implemented in Java.

在本教程中,我们已经看到了Fail-Safe和Fail-Fast Iterators的含义以及如何在Java中实现这些。

The complete code presented in this article is available over on GitHub.