You can know the source of the error from the reported error checkForComodification() ,如果要避免错误需要保持 modCount != expectedModCount 为 false 。 list.remove(Object)会去调用fastRemove(int)方法,这个时候必然会去修改 modCount ,这个时候就会出现错误。 Iterator<String> iterator = list.iterator() ;这个方法的实现就是返回一个内部类 Itr,(迭代的过程都是使用的这个类),但是为什么这个 iterator.remove() 不会出现错误了,原因在与这个方法的实现是在进行实际的 ArrayList.this.remove 之前进行的 checkForComodfication 检查,remove 之后又使 expectedModCount = modCount, so no error will occur.
Itr.remove implementation
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
If there is anything wrong, please point it out @ChaCha哥 @puluyinyi
In the case of a single thread, when deleting elements when traversing the List, you must use the remove method of Iterator instead of the remove method of List, otherwise a ConcurrentModificationException will occur. Just imagine if a teacher is counting the number of students in the entire class, and if the students don't follow the rules and go out and come in, the teacher will definitely not be able to count them.
In the case of multi-threading, refer to one of my blogs: http://xxgblog.com/2016/04/02...
First of all, this involves multi-threaded operations. Iterator does not support multi-threaded operations. The List class will maintain a modCount variable internally to record the number of modifications Example: ArrayList source code
protected transient int modCount = 0;
Every time an Iterator is generated, the Iterator will record the modCount. Each time the next() method is called, the record will be compared with the modCount of the external class List. If it is found to be unequal, a multi-threaded editing exception will be thrown.
Why do you do this? My understanding is that you created an iterator, and the iterator is tightly coupled with the content of the collection to be traversed, which means that the content of the collection corresponding to this iterator is the current content. I definitely don’t want to do it in my bubble sort. When , there are still threads inserting data into my collection, right? So Java uses this simple processing mechanism to prevent the collection from being modified during traversal.
As for why deleting "1" is enough, the reason lies in the hasNext() method of foreach and iterator. The syntactic sugar of foreach is actually
while(itr.hasNext()){
itr.next()
}
So every loop will execute hasNext() first, so take a look at how ArrayList’s hasNext() is written:
public boolean hasNext() {
return cursor != size;
}
cursor is a variable used to mark the position of the iterator. The variable starts from 0, and each time next is called, it performs a +1 operation, so: After your code deletes "1", size=1, cursor=1, this When hasNext() returns false, the loop ends, so your iterator does not call next to find the second element, so there is no way to detect modCount, so there will be no multi-threaded modification exception But when you delete "2" , the iterator called next twice. At this time, size=1, cursor=2, and hasNext() returned true, so the iterator foolishly called next() again, which also caused modCount to be unequal and threw Exception for multi-threaded modification.
When your collection has three elements, you will magically find that deleting "1" will throw an exception, but deleting "2" will not be a problem. The reason is that the execution order of the above program is Consistent.
Because the number in the collection changes when you add or delete elements, problems may occur when traversing. For example, if a collection has 10 elements, it should be traversed 10 times. When you add Or if an element is deleted, the number of traversals is incorrect, so an error will be reported
You can know the source of the error from the reported error
checkForComodification()
,如果要避免错误需要保持modCount != expectedModCount
为false
。list.remove(Object)
会去调用fastRemove(int)
方法,这个时候必然会去修改modCount
,这个时候就会出现错误。Iterator<String> iterator = list.iterator()
;这个方法的实现就是返回一个内部类Itr
,(迭代的过程都是使用的这个类),但是为什么这个iterator.remove()
不会出现错误了,原因在与这个方法的实现是在进行实际的ArrayList.this.remove
之前进行的checkForComodfication
检查,remove
之后又使expectedModCount = modCount
, so no error will occur.Itr.remove
implementationIf there is anything wrong, please point it out @ChaCha哥 @puluyinyi
In the case of a single thread, when deleting elements when traversing the List, you must use the remove method of Iterator instead of the remove method of List, otherwise a ConcurrentModificationException will occur. Just imagine if a teacher is counting the number of students in the entire class, and if the students don't follow the rules and go out and come in, the teacher will definitely not be able to count them.
In the case of multi-threading, refer to one of my blogs: http://xxgblog.com/2016/04/02...
First of all, this involves multi-threaded operations. Iterator does not support multi-threaded operations. The List class will maintain a modCount variable internally to record the number of modifications
Example: ArrayList source code
Every time an Iterator is generated, the Iterator will record the modCount. Each time the next() method is called, the record will be compared with the modCount of the external class List. If it is found to be unequal, a multi-threaded editing exception will be thrown.
Why do you do this? My understanding is that you created an iterator, and the iterator is tightly coupled with the content of the collection to be traversed, which means that the content of the collection corresponding to this iterator is the current content. I definitely don’t want to do it in my bubble sort. When , there are still threads inserting data into my collection, right? So Java uses this simple processing mechanism to prevent the collection from being modified during traversal.
As for why deleting "1" is enough, the reason lies in the hasNext() method of foreach and iterator. The syntactic sugar of foreach is actually
So every loop will execute hasNext() first, so take a look at how ArrayList’s hasNext() is written:
cursor is a variable used to mark the position of the iterator. The variable starts from 0, and each time next is called, it performs a +1 operation, so:
After your code deletes "1", size=1, cursor=1, this When hasNext() returns false, the loop ends, so your iterator does not call next to find the second element, so there is no way to detect modCount, so there will be no multi-threaded modification exception
But when you delete "2" , the iterator called next twice. At this time, size=1, cursor=2, and hasNext() returned true, so the iterator foolishly called next() again, which also caused modCount to be unequal and threw Exception for multi-threaded modification.
When your collection has three elements, you will magically find that deleting "1" will throw an exception, but deleting "2" will not be a problem. The reason is that the execution order of the above program is Consistent.
Because the number in the collection changes when you add or delete elements, problems may occur when traversing. For example, if a collection has 10 elements, it should be traversed 10 times. When you add Or if an element is deleted, the number of traversals is incorrect, so an error will be reported
Just delete them in reverse order. Anyway, try not to remove the list. You can add delete mark
The yellow description in the document is very interesting.
You still need to look at the source code of
ArrayList
, you will know it at a glance.Just delete it in reverse order
ArrayList is not thread-safe, which means you modify the List while traversing.
ArrayList will throw a concurrent modification exception in this case.