删除 List 元素的三种正确方法

// 每次都会计算list.size()比较耗费性能
        public static void remove1 (List < String > list, String target){
            for (int i = list.size() - 1; i >= 0; i--) {
                String item = list.get(i);
                if (target.equals(item)) {
                    list.remove(item);
                }
            }
            print(list);
        }

//通过 CopyOnWriteArrayList 解决了 List的并发问题。每次remove的都是复制出的list
        public static void remove2 (ArrayList < String > list, String target){
            final CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<String>(list);
            for (String item : cowList) {
                if (item.equals(target)) {
                    cowList.remove(item);
                }
            }
            print(cowList);
        }

        public static void remove3 (List < String > list, String target){
            Iterator<String> iter = list.iterator();
            while (iter.hasNext()) {
                String item = iter.next();
                if (item.equals(target)) {
                    iter.remove();
                }
            }
            print(list);
        }

Iterator的定义代码

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

            final void checkForComodification() {
                if (modCount != expectedModCount) throw new ConcurrentModificationException();
            }
        }

通过代码我们发现 Itr 是 ArrayList 中定义的一个私有内部类,
在 next、remove方法中都会调用 checkForComodification 方法,该方法的作用是判断 modCount != expectedModCount是否相等,如果不相等则抛出ConcurrentModificationException异常。
每次正常执行 remove 方法后,都会对执行expectedModCount = modCount赋值,保证两个值相等,那么问题基本上已经清晰了,在 foreach 循环中执行 list.remove(item);,对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改,因此抛出了ConcurrentModificationException异常。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值