java.util.ConcurrentModification

2019-12-02  本文已影响0人  禾叶super

在ArrayList使用for循环迭代时,remove元素,会出现ConcurrentModificationException异常 。

public class Test2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        for (Integer a:list) {
            if (a == 1){
                list.remove(i);
            }
            System.out.println(a);
        }
    }
}
image.png

出现异常的原因是什么

/*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     */
    private void fastRemove(int index) {
        modCount++;
        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
    }

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

让我们看一下源码,list的remove操作的方法中modCount++ ,modCount值自增1,致使checkForComodification()方法中expectedModCount不等于modCount ,因此抛出ConcurrentModificationException异常。

解决方案:引入Java 8的新特性stream

public class Test2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        List<Integer> list1 = list.stream().filter(i -> i!=1).collect(Collectors.toList());
        for (Integer a:list1) {
            System.out.println(a);
        }

    }
}

想了解更多stream特性,参考如下链接。
参考链接:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html

上一篇下一篇

猜你喜欢

热点阅读