zoukankan      html  css  js  c++  java
  • java.util.concurrentmodificationexception 当在循环中 给List 添加对象或者 remove 对象是时候

    最近在项目中再循环中删除当前list 的对象或者添加list的对象的时候   报了这个错误。

    在Console 中可以发现是这个方法中报了错误:

    checkForComodification()

    /**
         * 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
            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();
                }
            }
    
            @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();
            }
        }

    从这里可以看到,这里会比较现在的 Count 是否是期待的   有点类似于 CAS 的思想 , 就是会比较下List 的坐标。

    那么我们该如何解决呢?

    对于 Remove 

    我们可以 把List  转换为  iterator  , 利用While  来进行 remove  。

    例子:

    Iterator<ImportResultEachRow<Test>> iterator = RecordList.iterator();
    while (iterator.hasNext()) {
                ImportResultEachRow<Test> item = iterator.next();
                if (StringUtils.isNotBlank(item.getTargetObject().getDeleted())
                        && !StringUtils.equals(item.getTargetObject().getDeleted().toUpperCase(), "Deleted")){
                    iterator.remove();
                }
            }

    这样子就可以在List 循环中删除掉  元素了。

    对于Add()

    同样的 我们也可以进行转换, 但是iterator 是没有提供Add 的方法, 所以我们可以用  ListIterator 这样子我们就可以使用add  方法来进行 添加元素了。

    
    
    ListIterator<ReportDTO> iterator = SameValueDays.listIterator();
    while (iterator.hasNext()) {
                ReportDTO oneRowInfo = iterator.next();
                        if (oneRowInfo.getAmount() == null && !hasOutward) {
                            ReportDTO otherRowInfo = new ReportDTO();
                            iterator.add(otherRowInfo ); 
      }
    }

    这样子就可以 放心的在循环中 添加了。

     对了 我这个方案 只能在  单线程中使用。  如果是多线程  请参考下面的文章。

    引用文章:http://www.cnblogs.com/dolphin0520/p/3933551.html

  • 相关阅读:
    Ubuntu 16.04 安装 Apache, MySQL, PHP7
    Ubuntu下apache2启动、停止、重启、配置
    织梦-数据库-表和字段说明手册
    DEDECMS去除后门隐患和漏洞以及冗余代码的方法
    Express使用html模板
    windows系统 安装MongoDB
    linux搭建node.js环境
    配置vuejs加载模拟数据
    安卓高级5 zXing
    安卓高级5 传感器和震动 模仿微信摇一摇Ui效果
  • 原文地址:https://www.cnblogs.com/mythdoraemon/p/10214435.html
Copyright © 2011-2022 走看看