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中删除元素不是每次都报错。满足以下条件之一不会报错:
- 循环的是数组而不是集合
- 使用迭代器的remove方法而不是集合的remove方法
- 删除后不能够进入下一次循环,而是立即结束。包括以下两种情况:使用break结束循环;删除集合的最后一个元素或倒数第二个元素
不过为了确保安全,还是不要在增强for中删除集合的元素了。
END