錯誤代碼還原
Iterator it = list.iterator();
while (it.hasNext()) {
Integer val = it.next(); // 獲取元素 1
if (val == target) {
it.next(); // ❌ 再次調用 next() 導致指鈕前移
list.remove(val); // 直接操作集合觸發 fail-fast
}
}
核心誤區
it.next() 是「獲取並前移」:每次調用都會移動游標,上例中循環體內調用兩次,導致跳過元素甚至越界。
- 直接調用
list.remove() 破壞迭代器狀態:ArrayList 通過 modCount 實現 fail-fast,迭代器檢測到結構性修改拋出 ConcurrentModificationException。
正確寫法:使用迭代器自身的 remove()
Iterator it = list.iterator();
while (it.hasNext()) {
Integer val = it.next(); // ① 獲取當前元素,游標後移
if (val == target) {
it.remove(); // ② 安全刪除,同步更新 modCount
}
}
Java 8+ 更簡潔寫法
// 1. removeIf(內部使用迭代器,線程不安全場景首選)
list.removeIf(val -> val == target);
// 2. Stream 過濾生成新列表(函數式風格)
List filtered = list.stream()
.filter(val -> val != target)
.collect(Collectors.toList());
原理解析
Iterator.remove() 是唯一合法的在迭代過程中修改集合的方式,它會更新迭代器內部的 expectedModCount。
modCount 機制:集合結構變更時 modCount++,迭代器每次操作前比對 expectedModCount == modCount,不一致拋異常。