• ArrayList删除--------ConcurrentModificationException问题


      在做项目中用到List存储数据,在里面做数据操作时候用到了删除。结果抛出ConcurrentModificationException异常。在这里把问题总结一下。

       原因:

    ArrayList进行foreach时所调用的迭代器(内部迭代器Itr)
    /**
    * An optimized version of AbstractList.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
    // expectedModCount是Itr特有的,modCount是公共的
    // expectedModCount和modCount默认是两者相等的;ArrayList进行删除修改都会更新modCount的值
    // 当ArrayList通过foreach进入它的内部迭代器Itr时,expectedModCount就被赋值为modCount的值,后续ArrayList进行增加或删除,只会更新modCount,而不会同步更新expectedModCount
    // 所以迭代器根据这两个值进行判断是否有并发性修改
    int expectedModCount = modCount;
     
    public boolean hasNext() {
    return cursor != size;
    }
    // ArrayList通过foreach(即增强for循环)来循环是调用的是ArrayList中内部类Itr的next()
    @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];
    }
    // ArrayList中迭代器删除方法
    public void remove() {
    if (lastRet < 0)
    throw new IllegalStateException();
    checkForComodification();
     
    try {
    ArrayList.this.remove(lastRet);
    cursor = lastRet;
    lastRet = -1;
    // 通过ArrayList中foreach(即通过ArrayList内部Itr的迭代器)进行删除元素
    // 此时会进行赋值 expectedModCount = modCount;而不会抛出异常
    expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
    throw new ConcurrentModificationException();
    }
    }
    final void checkForComodification() {
    if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
    }
    }
    ArrayList通过foreach迭代是调用的其内部类Itr的next方法。如果通过foreach循环,要去除某些元素,只能通过迭代器删除。因为迭代器删除后会对expectedModCount = modCount设置,不会再循环过程因为expectedModCount 和 modCount值不相等而抛出异常了。如果是通过ArrayList的删除则只会对modCount进行更新,但是ArrayList内部迭代器Itr的属性expectedModCount却没有得到更新,所以抛异常。
     
    解决: List.iterator() 直接用迭代器去迭代,然后去删除元素。
     
  • 相关阅读:
    面试问题 集锦
    减少 lwip 消耗 的 RAM
    Blocking Master Example QT 自带 的 serial 即 串口 例子
    32位 的变量 用于表示 ms ,可以表示多少天那?
    centos 腾讯云 今天买了 18个月
    Linux BLE 基于 树莓派
    树莓派 4G模块 PPP 拨号 NDIS 拨号
    linux备份还原命令
    centos7中/tmp文件保存天数
    centos7查看可登陆用户
  • 原文地址:https://www.cnblogs.com/technologykai/p/9050796.html
Copyright © 2020-2023  润新知