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

2021-09-30  本文已影响0人  Jam_Lin

近期在浏览增强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

上一篇下一篇

猜你喜欢

热点阅读