近期在瀏覽增強(qiáng)for循環(huán)(foreach)相關(guān)頁(yè)面時(shí)發(fā)現(xiàn)大莫,增強(qiáng)for循環(huán)中不能使用刪除(學(xué)了那么久居然不知道嗚嗚嗚)呼猪。但是阱飘,我在近期的項(xiàng)目中就有在增強(qiáng)for循環(huán)中進(jìn)行刪除的操作驹吮,也沒(méi)見(jiàn)報(bào)錯(cuò)依疼,操作正常剖煌。這部分的代碼如下:
for (CollectiveUser cu : cus) {
if (Objects.equals(cu.getUserId(), s.getUserId())) {
cus.remove(cu);
break;
}
}
是不是其中的break阻止了報(bào)錯(cuò)呢材鹦?于是進(jìn)行了如下實(shí)驗(yàn):
分別運(yùn)行以下三段代碼:
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);
}
發(fā)現(xiàn)只有第1段代碼報(bào)錯(cuò)(java.util.ConcurrentModificationException),而第2段和第3段沒(méi)有報(bào)錯(cuò)耕姊。
網(wǎng)上也有很多文章講了桶唐,增強(qiáng)for循環(huán)是Java中的一種語(yǔ)法糖,能夠用來(lái)對(duì)數(shù)組或者集合進(jìn)行遍歷茉兰。其中尤泽,對(duì)于數(shù)組,使用的是下標(biāo)進(jìn)行遍歷:
int array[] = {1, 2, 3};
for(int len$ = array$.length, i$ = 0; i$<len$; ++i$) {
int i = array$[i$];
{
System.out.println(i);
}
}
而對(duì)于集合,則使用迭代器的形式:
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);
}
}
網(wǎng)上說(shuō)法如下:
迭代器內(nèi)部的每次遍歷都會(huì)記錄List內(nèi)部的modcount當(dāng)做預(yù)期值坯约,然后在每次循環(huán)中用預(yù)期值與List的成員變量modCount作比較熊咽,但是普通list.remove調(diào)用的是List的remove,這時(shí)modcount++闹丐,但是iterator內(nèi)記錄的預(yù)期值=并沒(méi)有變化网棍,所以會(huì)報(bào)錯(cuò),但是如果在Iterator中調(diào)用remove,這時(shí)會(huì)同步List的modCount到Iterator中妇智,故不再報(bào)錯(cuò)
使用迭代器中的remove方法也不會(huì)報(bào)錯(cuò):
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方法滥玷,還是會(huì)報(bào)錯(cuò)
}
}
由此可以發(fā)現(xiàn),Java中的增強(qiáng)for中刪除元素不是每次都報(bào)錯(cuò)巍棱。滿足以下條件之一不會(huì)報(bào)錯(cuò):
- 循環(huán)的是數(shù)組而不是集合
- 使用迭代器的remove方法而不是集合的remove方法
- 刪除后不能夠進(jìn)入下一次循環(huán)惑畴,而是立即結(jié)束。包括以下兩種情況:使用break結(jié)束循環(huán)航徙;刪除集合的最后一個(gè)元素或倒數(shù)第二個(gè)元素
不過(guò)為了確保安全如贷,還是不要在增強(qiáng)for中刪除集合的元素了。
END