• 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() 直接用迭代器去迭代,然后去删除元素。
     
  • 相关阅读:
    [Python] 项目的配置覆盖与合并
    [PHP] dompdf 使用记录
    Ubuntu16.04 desktop 设置共享文件夹 -- 图形界面配置
    (转)你不得不看的六篇知识图谱落地好文
    转 python2 与 python3 的编码
    (转) C#使用ODP.NET(Oracle.ManagedDataAccess.dll)操作Oracle数据库
    django & celery
    (转) 解决django项目部署到nginx+uwsgi服务器后 admin页面样式消失的问题
    Ubuntu 16.04 安装 SVN-Client (RaabitVCS)
    python 2.7
  • 原文地址:https://www.cnblogs.com/technologykai/p/9050796.html
Copyright © 2020-2023  润新知