Java 中 for循环中删除List元素的问题

for循环,会导致List中的元素的下标变动

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        // i < 5 是为了不发生空之争一场
        for (int i = 0; i < 5; i++) {
            System.out.println(list.get(i));
            if (list.get(i) == 1) {
                list.remove(i);
            }
        }
    }
    // 输出
    // 1
    // 3
    // 4
    // 5
    // 6

从输出可以看到list.remove(0)之后,2并没有输出,因为删除元素导致了index 0之后的元素集体前移了

增强for循环

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        for (String i : list) {
            if (i.equals("a")) {
                list.remove(i);
            }
            System.out.println(i);
        }
    }

输出:

    // 输出
    a
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)

可以看到,抛出了异常,但是a被打印出来了,所以是下次循环出了问题。可以看出增强for循环其实就是使用了迭代器。

定位到报错的位置:

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

其中,modCount代表list被修改的次数,expectedModCount表示这个迭代器期望该集合被修改的次数。其值是在ArrayList.iterator方法被调用的时候初始化的。
再看remove(Object o)方法的操作

    public boolean remove(Object o) {
        final Object[] es = elementData;
        final int size = this.size;
        int i = 0;
        found: {
            if (o == null) {
                for (; i < size; i++)
                    if (es[i] == null)
                        break found;
            } else {
                for (; i < size; i++)
                    if (o.equals(es[i]))
                        break found;
            }
            return false;
        }
        fastRemove(es, i);
        return true;
    }
    
        private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        if ((newSize = size - 1) > i)
            System.arraycopy(es, i + 1, es, i, newSize - i);
        es[size = newSize] = null;
    }

可以看到,只修改了modCount,没有修改expectedModCount,所以在调用next()方法,就会抛出了异常

我的个人博客有空来坐坐

https://www.wangyanan.online

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值