美文网首页
Java增强for循环中的删除问题

Java增强for循环中的删除问题

作者: Jam_Lin | 来源:发表于2021-09-30 15:03 被阅读0次

    近期在浏览增强for循环(foreach)相关页面时发现,增强for循环中不能使用删除(学了那么久居然不知道呜呜呜)。但是,我在近期的项目中就有在增强for循环中进行删除的操作,也没见报错,操作正常。这部分的代码如下:

    for (CollectiveUser cu : cus) {
        if (Objects.equals(cu.getUserId(), s.getUserId())) {
            cus.remove(cu);
            break;
        }
    }
    

    是不是其中的break阻止了报错呢?于是进行了如下实验:

    分别运行以下三段代码:

    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    for (Integer obj : list) {
        if (obj == 2) {
            System.out.println(obj);
            list.remove(obj);  // 一边迭代一边删除
            System.out.println(obj);
    //                break;
        }
        System.out.println(obj);
    }
    
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    for (Integer obj : list) {
        if (obj == 2) {
            System.out.println(obj);
            list.remove(obj);  // 一边迭代一边删除
            System.out.println(obj);
            break;
        }
        System.out.println(obj);
    }
    
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    for (Integer obj : list) {
        if (obj == 3) {
            System.out.println(obj);
            list.remove(obj);  // 一边迭代一边删除
            System.out.println(obj);
    //                break;
        }
        System.out.println(obj);
    }
    

    发现只有第1段代码报错(java.util.ConcurrentModificationException),而第2段和第3段没有报错。


    报错信息

    网上也有很多文章讲了,增强for循环是Java中的一种语法糖,能够用来对数组或者集合进行遍历。其中,对于数组,使用的是下标进行遍历:

    int  array[] = {1, 2, 3};
    for(int  len$ = array$.length, i$ =  0; i$<len$; ++i$) {
        int  i = array$[i$];
        {
            System.out.println(i);
        }
    }
    

    而对于集合,则使用迭代器的形式:

    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    for (java.util.Iterator i$ = list.iterator(); i$.hasNext(); ) {
        String s = (String) i$.next();
        {
            System.out.println(s);
        }
    }
    

    网上说法如下:

    迭代器内部的每次遍历都会记录List内部的modcount当做预期值,然后在每次循环中用预期值与List的成员变量modCount作比较,但是普通list.remove调用的是List的remove,这时modcount++,但是iterator内记录的预期值=并没有变化,所以会报错,但是如果在Iterator中调用remove,这时会同步List的modCount到Iterator中,故不再报错

    使用迭代器中的remove方法也不会报错:

    Iterator it = list.iterator();
    while (it.hasNext()) {
        Object obj = it.next();
        System.out.println(obj);
        if (obj.equals(1)) {
            it.remove(); // 迭代器的remove方法
            // list.remove(obj); // 集合的remove方法,还是会报错
        }
    }
    

    由此可以发现,Java中的增强for中删除元素不是每次都报错。满足以下条件之一不会报错:

    1. 循环的是数组而不是集合
    2. 使用迭代器的remove方法而不是集合的remove方法
    3. 删除后不能够进入下一次循环,而是立即结束。包括以下两种情况:使用break结束循环;删除集合的最后一个元素或倒数第二个元素

    不过为了确保安全,还是不要在增强for中删除集合的元素了。

    END

    相关文章

      网友评论

          本文标题:Java增强for循环中的删除问题

          本文链接:https://www.haomeiwen.com/subject/yxeenltx.html