简体   繁体   中英

Java - Will concurrent modification exception occur while using classic for loop?

Is there is a chance for getting concurrent modification exception occur while using classic for loop?

import java.util.*;

class IterTest{
    public static void main(String[] args){
        List<Integer> nums = new ArrayList<>();
        nums.add(18);
        nums.add(1);
        nums.add(14);
        nums.add(13);
        System.out.println("Nums ->"+nums);
        int len = nums.size();
        for(int index=0;index < len ;index++){          
            System.out.println(" Current >>"+nums.get(index));
            System.out.println(" Removing >>"+nums.remove(index));          
        }
    }
}

No, there is no chance. Concurrent modification exception may occur while using iterators, see What are fail-safe and fail-fast iterators in java

No, this code won't give a ConcurrentModificationException . That exception typically occurs when a view of a collection is "spoiled" by the collection being changed out from underneath it. Typical examples of this are modifying a collection while it's being iterated by an Iterator (which is implicitly used in an enhanced-for statement) or by getting a subList() , modifying the underlying list, and then continuing to use the sublist.

However, this code will run into the same condition that "spoils" the loop, except that a different exception will be thrown. The loop bounds are based on the list's initial size. However, the loop body removes elements from the list, so the code will eventually index outside the bounds of the list, resulting in IndexOutOfBoundsException .

How to fix this code depends on what you're trying to do. It might initially seem sensible to avoid ConcurrentModificationException by using list indexes instead of an Iterator . However, if the list is structurally modified (that is, elements are added or removed) during the loop, the index and loop bounds need to be adjusted carefully, otherwise elements may be skipped, duplicated, or an IndexOutOfBoundsException may occur.

No, as other answers have suggested, ConcurrentModificationException will not occur in the given code.

So when does ConcurrentModificationException occur?

In single threaded environment it will usually occur when you use Iterators to loop over collection and modify it simultaneously.

Why?

If you check the source code of Iterator implementations, it always does checkForComodification() whenever you use any method of iterator(eg next(), remove()). The code for that method in ArrayList.java for instance is:

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

Where modCount is a static variable maintained at ArrayList class level which signifies the number of times this list has been structurally modified. And expected modification count expectedModCount , is maintained at Iterator class level, which is initially equal to modCount.

Thus whenever the expected number of modifications do not match the modifications actually done, you get the exception.

As in your case you have not used any of this, there will be no check for Co-modification, and hence you will not get ConcurrentModificationException .

Note: As stated in this answer , you will get IndexOutOfBoundsException since you have checked index < len in your for loop and len is initialized to initial size of array. A simple solution to this would be:

 for(int index=0;index < nums.size;index++)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM