foreach循环中remove引起java.util.ConcurrentModificationException异常
来源:互联网 发布:广州知行通航 编辑:程序博客网 时间:2024/06/10 16:26
1.引起异常代码
public void test1(){ List<String> list = new ArrayList<String>(); list.add("2"); list.add("2"); list.add("2"); for (String temp : list) { if ("2".equals(temp)) { list.remove(temp); } }}
2.上面代码经过编译再反编译去除语法糖后,得到以下代码
public void test1() { ArrayList list = new ArrayList(); list.add("2"); list.add("2"); list.add("2"); Iterator var3 = list.iterator(); while(var3.hasNext()) { String i = (String)var3.next(); if("2".equals(i)) { list.remove(i); } } }
可以看出,经过编译后,list类型的foreach循环实质上是使用了iterator。但是,循环体中的remove依然是直接使用ArarryList的remove,而不是iterator的。下面我们看下相关的源码,便可知道报错的原因。
3.ArarryList的remove源码
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false;}private void fastRemove(int index) { modCount++; //修改次数 int numMoved = size - index - 1; if (numMoved > 0) //将除了被remove的元素之后复制回原来集合 System.arraycopy(elementData, index+1, elementData, index,numMoved); elementData[--size] = null;}
每次执行ArarryList的remove方法,都会将修改次数变量modCount+1
4.ArarryList的私有内部类Itr源码
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; //修改次数 public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") 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]; } 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(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
内部类Itr中的remove方法实际上是先调用了ArrayList的remove,再将修改次数modCount同步到内部类的expectedModCount ,保持两者一致。
明显,问题代码是由于先调用了list.remove(),导致modCount和expectedModCount不相等,Itr执行next()时验证发现两个值不一致,抛出ConcurrentModificationException异常。因此,涉及到remove操作时应直接使用iterator,不可使用foreach语法糖。
阅读全文
0 0
- foreach循环中remove引起java.util.ConcurrentModificationException异常
- java foreach循环中调用remove 抛出java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 集合remove异常
- 解决 java.util.ConcurrentModificationException map不能在循环时remove
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException 异常
- 异常:java.util.ConcurrentModificationException
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 异常
- java.util.ConcurrentModificationException 异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- 算法设计:统计数字问题
- Java学习笔记(7)- Java系统类
- 操作系统的发展史(科普章节)
- Tomcat本地部署 Android内网加载
- 结构经典例题,用上了typedef 再进行指针优化
- foreach循环中remove引起java.util.ConcurrentModificationException异常
- mysql 事务
- 2卷积神经网络相关API详解-2.1TensorFlow之卷积操作API
- es6<一>
- Spark之CASE...WHEN...THEN...的两种实现方式
- js日常
- 流程进度显示
- Android自定义控件5----继承View通讯录索引功能之3在按下或和移动时显示更新提示字母
- java基础知识(二 对象和类)