(1)、使用foreach进行迭代
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("123");
list.add("345");
list.add("456");
for (String str:list) {
if (str.startsWith("1")){
list.remove(str);
}
}
System.out.println(list);
}
会出现如下异常:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at com.datahunter.cn.TestModel.TestCoolection.main(TestCoolection.java:20)
为什么会造成该异常:源码分析
在ArraysList中的Itr内部类中 会使用迭代器去迭代而以上代码编译后的结果为:
Iterator var2 = list.iterator();
while(var2.hasNext()) {
String str = (String)var2.next();
if (str.startsWith("1")) {
list.remove(str); // 调用list中remove方法
}
}
会执行next方法做验证。
public E next() {
checkForComodification(); //对modCount和expectedModCount验证
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}
当使用 list.remove(str)方法时,并没有对于modCount和expectedModCount进行同步操作则会出现异常情况
(2)、使用for循环遍历元素时并不会出现异常,移除元素
for (int i=0;i<list.size();i++){
if (list.get(i).startsWith("1")){
list.remove(i);
}
}
System.out.println(list);
}
为什么不会出现异常
public E remove(int index) {
rangeCheck(index);//对于数组长度的校验,并没有对操作次数做校验。
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
(3)、使用迭代器遍历元素,移除元素
迭代器会执行Itr内部类
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
if (iterator.next().startsWith("1")){
iterator.remove();
}
}
System.out.println(list);
执行Itr内部类中的remove方法();
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); //验证modCount与expectedModCount
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount; //会将modCount和expectedModCount进行同步
//modCount 指的是list每一次操作的统计数值
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
List 中的remove源码
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
System.arraycopy()效果如下图