1. 程式人生 > 其它 >還在 for 迴圈中 remove 元素?必須勸退……

還在 for 迴圈中 remove 元素?必須勸退……

來源:juejin.cn/post/6844903906449358856

業務中有需要過濾的需求,踩了 foreach 的坑。本來是這樣寫的:

user.forEach(u -> {
   ageList.forEach(a -> {
        if (u.getId().equals(a)) {
            user.remove(u);
            }
        });
    });
}

改進後是這樣的:

Iterator<SocNearbyRespDto> ui = user.iterator();
    while (ui.hasNext()){
        SocNearbyRespDto u = ui.next();
        ageList.forEach(a->{
            if (!u.getId().equals(a)){
                ui.remove();
            }
        });
    }
}

Java 中通常有三種迴圈

for (int i = 0; i < list.size(); i++) {
    System.out.print(list.get(i) + ",");
}

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + ",");
}

for (Integer i : list) {
    System.out.print(i + ",");
}

list.foreach 跟程式碼中第三種增強型 for 迴圈一樣,反編譯的內容是

    Integer i;
    for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
        i = (Integer)iterator.next();        
    }

這樣在 for 迴圈中呼叫會出現 ConcurrentModificationException 異常。

Iterator是工作在一個獨立的執行緒中,並且擁有一個 mutex 鎖。Iterator被建立之後會建立一個指向原來物件的單鏈索引表,當原來的物件數量發生變化時,這個索引表的內容不會同步改變,所以當索引指標往後移動的時候就找不到要迭代的物件,所以按照 fail-fast 原則 Iterator 會馬上丟擲java.util.ConcurrentModificationException

異常。

所以改成用 Iterator.remove() 就好了。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!