遍历集合并删除指定项报UnsupportedOperationException和ConcurrentModificationException解决思路

84 阅读1分钟

业务场景:对一个集合中,删除符合条件的元素

代码如下

List<Integer> list = Arrays.asList(1,2,5,6,8,9);
for (Integer e: list
     ) {
    list.remove(e);
}

最后运行报错

image.png

image.png 可以看到Arrays.asList()方法创建出来的并不是java.util.ArrayList类,而是java.util.Arrays.ArraysList,是Arrays中的静态内部类,虽然这个静态内部类继承了AbstractList,但它并没有重写remove方法,所以会报UnsupportedOperationException

List<Integer> list = new ArrayList<>(Arrays.asList(1,2,5,6,8,9));
//       
        for (Integer e: list
             ) {
            list.remove(e);
        }

将Arrays.asList()方法的返回对象包装一下,就不会有UnsupportedOperationException,但是执行会报ConcurrentModificationException,这是因为添加或者删除操作会改变ArrayList类中的modcount,然而ArrayList中的内部类Itr的expectedModCount与modcount就不相等了,如果使用iterator遍历并删除,怎不会有这个并发异常,详见代码

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

在remove方法中设置了expectedModCount = modCount,会进行修改次数记录的同步