還在 for 迴圈中 remove 元素?必須勸退……
阿新 • • 發佈:2022-03-18
來源: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最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!