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