Search code examples
javahashmapconcurrentmodification

why iterator is not throwing concurrentmodification exception?


why does this method not throw a concurrent modification? if if(next.equals("3") it does not. However, i change it to equals("1") it does. what is happening here?

    private void checkConcurrentModification(){

        Map<String, Integer> map = new HashMap<>();

        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);


        Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();

        while(iterator.hasNext()){
            String next = iterator.next().getKey();
            map.put(next, 1);
            if(next.equals("3")){ //does not throw exception
 //if(next.equals("1")){ //throws exception
                map.put("4", 4);
            }
        }

        for(Entry<String, Integer> entry : map.entrySet()){
            System.out.println("entry key and value" +entry.getKey() + " : " +entry.getValue());
        }

    }


prints:
entry key and value1 : 1
entry key and value2 : 1
entry key and value3 : 1
entry key and value4 : 4

Solution

  • This depends on the the implementation of HashMap.

    If you run this under Java 7, then with the if (next.equals("3")) it will throw a ConcurrentModificationException, and with 1, it won't.

    If you run this under Java 8, then with 3 it will not throw the exception, and with 1, it will.

    The reason for this is that when you iterate the map under Java 7, the first key is going to be the 3 and the last is 1. So you are modifying the value while you still have other values to iterate.

    Under Java 8, the first key in the iteration is 1 and the last is 3.

    If you modify the map when you have encountered the last key, it will not check that modification, because it only checks it the next time you try to call next(), but after the last value, hasNext() returns false, so next() is not called and the exception is avoided.