在AbstractList中,有一个全局变量madCount,记录了结构性改变的次数。结构性改变指的是那些修改了列表大小的操作,在迭代过程中可能会造成错误的结果。
modCount交由迭代器(Iterator)和列表迭代器(ListIterator)使用,当进行next()、remove()、previous()、set()、add()等操作时,如果madCount的值意外改变,那么迭代器或者列表迭代器就会抛出ConcurrentModificationException异常。
modCount和expectedModCount是用于表示修改次数的,其中modCount表示集合的修改次数,这其中包括了调用集合本身的add方法等修改方法时进行的修改和调用集合迭代器的修改方法进行的修改。而expectedModCount则是表示迭代器对集合进行修改的次数。
expectedModCount是每次迭代开始前会赋值 expectedModCount=modCount
List<String> tmpList = new ArrayList<>();
tmpList.add("Hello");
tmpList.add("My");
tmpList.add("Son");
// modCount表示集合的修改次数
// expectedModCount则是表示迭代器中对集合进行修改的次数 初始赋值expectedModCount=modCount,迭代器开始后这个用来判断是否有线程并发修改了集合
// 增强for调用ArrayList,class-Itr里的HasNext()(hasNext里面有cursor!=size的判断) ->next()(next里面会检查modCount和expectCount)
for (String curStr : tmpList) {
// 如果这里为Hello就会报错 , Hello删除后modCount=4,expectCount=3
// 如果是My list.size-1=2,此时下次循环调用HasNext() cursor==size=2推出循环,此时modCont=4,expectCount=3
if ("My".equals(curStr)) {
tmpList.remove(curStr); // modCount++,不会修改expectCount
// tmpList.add("asd"); 这个也会modCount++,会有问题
}
}
List<String> lis4 = new ArrayList<>();
lis4.add("apple");
lis4.add("apple2");
Iterator<String> it = lis4.iterator();
while (it.hasNext()) {
// 增强for调用ArrayList,class-Itr里的next()
String str = it.next(); // 检查modCount=3 != expectCount=2
if (str.equals("apple")) {
it.remove(); // iterator的remove会重新赋值 expectCount = modCount =3
}
}
List<String> lis = new ArrayList<>();
lis.add("apple");
Iterator<String> it2 = lis.iterator();
while (it2.hasNext()) {
// 增强for调用ArrayList,class-Itr里的next()
String str = it2.next(); // 检查modCount=2 != expectCount=1
if (str.equals("apple")) {
lis.add("asd"); // modCount=2
}
}
https://blog.csdn.net/dashu5943/article/details/101560491
ArrayList中modCount的作用_QasimCyrus的博客-CSDN博客_arraylist modcount