使用普通for循环时删除元素
验证代码:
List<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));list.remove(i);}// 只会打印出1,3,会漏掉2
此时删除元素,会导致元素前移,当i为1时,实际上访问的时原数组下标为2的数据,而原数组中下标为1的,此时已经前移到下标0处,所以不能在使用普通for循环时删除元素
使用增强for循环时删除元素
原始代码:
List<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");for (String s : list) {list.remove(s);}
增强for循环在编译后会被优化为迭代器
反编译代码:
List<String> list = new ArrayList();list.add("1");list.add("2");list.add("3");Iterator var4 = list.iterator();while(var4.hasNext()) {String s = (String)var4.next();list.remove(s);}
而迭代器在每次使用next方法获取下一个元素时,会检查内部的modCount变量与expectedModCount变量是否一致,而List的remove方法在移除元素时,不会更新迭代器中的expectedModCount变量,只更新了全局的modCount,导致在next时实际值与期望值不符。
ArrayList的remove源码:

迭代器的next源码(红线标注的地方则为检查modCount值的方法):
]
使用迭代器时删除元素
验证代码:
List<String> list = new ArrayList();list.add("1");list.add("2");list.add("3");Iterator iterator = list.iterator();while(iterator.hasNext()) {String next = (String)iterator.next();iterator.remove();}
迭代器删除时,必须先调用next方法,然后在调用remove方法
原因: 在remove时使用lastRet下标变量去删除数组元素的,而初始化时默认的时-1且每次删除后都会置为-1,如果不调用next方法将当前元素的下标赋予lastRet,则remove时,会直接抛出非法状态异常
迭代器remove方法:

红线1的位置调用ArrayList的remove方法移除元素,此时修改了modCount,
红线2的位置将modCount值同步到了expectedModCount变量
并在1,2之间的代码更新了下一次下标的位置
同步后在下一次next时,检查modCount就不会抛出ConcurrentModificationExecption异常
