ConcurrentModificationException
来源:互联网 发布:乐高机器人编程书 编辑:程序博客网 时间:2024/05/16 14:19
问题代码:
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { if (iterator.next().equals("c")) { // list.remove("c");// 报错:ConcurrentModificationException iterator.remove();// 可以运行 } }}
ArrayList的remove()源码:
/** * 按下标删除 */public E remove(int index) { rangeCheck(index); modCount++;// 修改次数加1!!! 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;}
/** * 按元素删除 */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++;// 修改次数加1!!! 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}
ArrayList的Iterator源码:
public Iterator<E> iterator() { return new 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();// 检查modCount和expectedModCount是否相等 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();// iterator的remove每次都会比较modCount和expectedModCount,若不等,则抛异常 try { ArrayList.this.remove(lastRet);// 执行ArrayList的remove cursor = lastRet; lastRet = -1; expectedModCount = modCount;// 同步modCount和expectedModCount,故iterator的remove不会抛异常 } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }}
由源码可以看出:
ArrayList的remove修改modCount,但未同步Iterator的expectedModCount,所以执行iterator.next()的checkForComodification()时,抛出异常;而Iterator的remove,其实也是执行ArrayList的remove,但是每次都会同步expectedModCount,所以不会抛出异常。
阅读全文
0 0
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException
- ConcurrentModificationException 异常
- oj分苹果(分啥分都自己吃)
- 2017年最好的25大发明,你最钟爱哪个?
- MongoDB 3.4 配置以 Windows 服务计划任务运行的详细步骤
- Linux系统上的虚拟终端
- PYTHON数据可视化(四)seaborn
- ConcurrentModificationException
- C语言单元小结(4)
- 读取bmp图片的文件头,与位图信息头
- nlp Python库之pynlpir
- Queueing at Bank
- android string中html标签与span设置方式
- LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- 利用C#实现杨辉三角形
- 使用Redis存储Nginx+Tomcat负载均衡集群的Session