为什么iterator,foreach遍历时不能进行remove操作?
Exception in thread "main" java.util.ConcurrentModificationException 并发修改异常引发的思考!
①list遍历删除元素时会报错,比如下面删除字符串"aa",也有遍历不报错的例子,看下面的例子
public class TestMain {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
array.add("cc");
array.add("aa");
array.add("bb");
array.add("aa");
for (String str : array) {
if("aa".equals(str)){
array.remove(str);
}
}
System.out.println(array.size());
}
}
console: java.util.ConcurrentModificationException
②下面删除字符串"aa"不会报错
public class TestMain {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
array.add("cc");
array.add("aa");
array.add("bb");
for (String str : array) {
if("aa".equals(str)){
array.remove(str);
}
}
System.out.println(array.size());
}
}
console : 2
③ 索引删除元素
public class TestMain {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
array.add("cc");
array.add("aa");
array.add("bb");
array.add("aa");
for(int i = 0;i < array.size();i++){
if("aa".equals(array.get(i))){
array.remove(i);
}
}
System.out.println(array.size());
}
}
console: 2
④ 迭代器删除元素
public static void main(String[] args) { ArrayList<String> array = new ArrayList<>(); array.add("cc"); array.add("aa"); array.add("bb"); array.add("ee"); Iterator<String> iterator = array.iterator(); while (iterator.hasNext()){ String e = iterator.next(); if("bb".equals(e)){ iterator.remove(); } }
System.out.println(array.size());
}
console: 3
从上述执行结果可以得出:
① foreach遍历删除后,下一个循环会报错,源码如下红色字体
// remove操作导致modCount++
private void fastRemove(int index) {
modCount++;
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
}
// 删除元素后,遍历下一个元素会先校验,不通过,报错
public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
② foreach遍历删除后,未报错?
其实原因很简单,因为第二个例子没有走iterator的next方法,删除了字符串"aa"之后,执行hasNext方法返回false直接退出遍历了,hasNext中就是判断cursor != size;此时的cursor是2,而size正好也是2,所以退出了遍历。
③ for循环删除,不会报错,按照索引删除
④ 迭代器的方式遍历,iterator.remove方法删除
总结: 1 foreach遍历,iterator遍历都不能在遍历的过程中使用list.remove或list.add操作,会报并发修改异常,遍历删除后加个break即可解决。
2 iterator遍历过程中如果需要删除可以使用iterator提供的remove()方法。
3 遍历根据元素索引删除是可行的。
以上属于个人心得,不对之处还望大佬指出。
关于http协议