Introduction to the

Many of you have tried the following code:

ArrayList<Object> list = ... ;for (Object object : list) {
    if{list.remove(object); }}Copy the code

Then will find throw Java. Util. ConcurrentModificationException is unusual, it is a complicated with abnormal. So what’s going on here? First, we need to introduce the enhanced for loop

Enhanced for loop

The enhanced for loop emerged after Java1.5, when the Collection implemented the Iterator interface. The code to enhance the for loop is as follows

for (Object object : list) {
    / / operation
}
Copy the code

To augment the for loop, we use the Iterator to iterate over it.

Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
    iterator.next();
    / / operation
}
Copy the code

So why does calling list.remove(object) in an enhanced for loop go wrong? So let’s look at the implementation class of Iterator under ArrayList: Itr class

Itr subclass

Itr subclasses are the implementation classes of Iterator and are part of the local inner classes that are private to ArrayList. I have captured part of the Itr class code as follows:

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int expectedModCount = modCount;

    Itr() {}

    public boolean hasNext(a) {
        returncursor ! = size; }@SuppressWarnings("unchecked")
    public E next(a) { checkForComodification(); . }final void checkForComodification(a) {
        if(modCount ! = expectedModCount)throw newConcurrentModificationException(); }}Copy the code

ElementData is an array of elements in an ArrayList, not posted above. ModCount Record How many times the elementData capacity is modified expectedModCount Record how many times the elementData capacity is modified when the iterator Itr is instantiated notice! : In the iterator, when the next method is executed, the checkForComodification method will be called to determine whether the capacity of elementData has been modified. Then look at the remove(object) method of ArrayList, which intercepts the following code:

public boolean remove(Object o) {
    for (int index = 0; index < size; index++)
	    if(Find the target element) {fastRemove(index);return true;
	    }
	return false;
}

private void fastRemove(int index) {
    modCount++;
    // Remove operation
}
Copy the code

The fastRemove method is called when the remove(object) method is called. ModCount++! Now copy the code from the beginning of the article and analyze it again:

ArrayList<Object> list = ... ;for (Object object : list) {
    if{list.remove(object); }}Copy the code

When list.remove is executed, modCount++ is executed. At this point the iterator iterates further down, executes the next method, and finds that modCount! = expectedModCount, so it throws the Java. Util. ConcurrentModificationException anomalies. The reason Iterator considers it to be a concurrent exception. Because you don’t operate inside the iterator, you operate outside the iterator. Isn’t there another solution? Have a drop.

The solution

So use Itr’s remove method. The Itr subclass overrides the remove method.

public void remove(a) {...try {
        ArrayList.this.remove(index of the element to be removed); . expectedModCount = modCount; }catch (IndexOutOfBoundsException ex) {
        throw newConcurrentModificationException(); }}Copy the code

ExpectedModCount = expectedModCount (” expectedModCount “) The complete code is as follows:

ArrayList<Object> list = ... ; Iterator<Object> iterator = list.iterator();while (iterator.hasNext()) {
    iterator.next();
    iterator.remove();
}
Copy the code

conclusion

I didn’t know that the enhanced for loop calls Iterator until I debug a wave. Still a little bit of goods.

Personal blog: colablog.cn/

If my article helps you, you can follow my wechat official number and share the article with you as soon as possible