業務中有須要過濾的需求,踩了 foreach 的坑。原本是這樣寫的。java
user.forEach(u -> {
ageList.forEach(a -> {
if (u.getId().equals(a)) {
user.remove(u);
}
});
});
}
複製代碼
改進後是這樣的。ui
Iterator<SocNearbyRespDto> ui = user.iterator();
while (ui.hasNext()){
SocNearbyRespDto u = ui.next();
ageList.forEach(a->{
if (!u.getId().equals(a)){
ui.remove();
}
});
}
}
複製代碼
Java 中一般有三種循環。spa
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
異常。code
因此改爲用 Iterator.remove()
就行了。對象