How Fail Fast Iterator identifies that the collection is modified?

UPDATED: 06 August 2016


Image gives you the abstract idea about How iterator identifies the modification on collection. Its one of the interview question asked as sub part of Fail Fast vs Fail Safe Iterator in Java. To understand it better I pulled out the source code of HashMap.

Source code (HashMap.java)
public class HashMap<K, V>...{
    transient int modCount;

    public V put(K key, V value) {
        return this.putVal(hash(key), key, value, false, true);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        ...
        ++this.modCount;
        ...
    }
 
    public Set<Map.Entry<K,V>> entrySet() {
        // this method internally uses HashIterator
    }

    abstract class HashIterator{
        int expectedModCount;  // for fast-fail
        ...
        HashIterator() {
            expectedModCount = modCount;
            ...
        }
 
        final Node nextNode() {
            ...
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            ...
            ...
        }
    }
}
So when you call method entrySet() of HashMap, It creates the object of inner class HashIterator with current value of modCount and set it in expectedModCount.

Now when nextNode() method is called it compares value of expectedModCount with parent class's (HashMap) modCount and if its not same then it throws ConcurrentModificationException.

Source code (FailFastExample.java)
/**
 * Example of Fail Fast using Map.
 * @author javaQuery
 * @date 4th August, 2016
 * @Github: https://github.com/javaquery/Examples 
 */
public class FailFastExample {
    public static void main(String[] args) {
        Map<String, Double> carPrice = new HashMap<String, Double>();
        carPrice.put("Porsche", 100000D);
        carPrice.put("Ferrari", 200000D);

        /* Iterate over Map */
        for(Map.Entry<String, Double> car : carPrice.entrySet()){
            System.out.println("Car: " + car.getKey());
            System.out.println("Price: " + car.getValue());
            
            /* Will cause java.util.ConcurrentModificationException */
            carPrice.put("Lamborghini", 300000D);
        }
    }
}

Output
Car: Ferrari
Price: 200000.0
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
 at com.javaquery.collections.map.FailFastExample.main(FailFastExample.java:23)

0 comments :