for (Person p : personList) {
if (p.getGender() == Gender.MALE) {
personList.remove(p); // 拋出 ConcurrentModificationException
}
}
modCount(修改次數)。modCount 變化(集合結構被修改),立即拋出 ConcurrentModificationException。remove/add/clear 而非迭代器的 remove()。remove()(標準做法)Iterator it = personList.iterator();
while (it.hasNext()) {
Person p = it.next();
if (p.getGender() == Gender.MALE) {
it.remove(); // 安全移除,同步更新 modCount
}
}
for (int i = personList.size() - 1; i >= 0; i--) {
if (personList.get(i).getGender() == Gender.MALE) {
personList.remove(i); // 索引不受後續元素位移影響
}
}
List toRemove = new ArrayList<>();
for (Person p : personList) {
if (p.getGender() == Gender.MALE) toRemove.add(p);
}
personList.removeAll(toRemove);
List filtered = personList.stream()
.filter(p -> p.getGender() != Gender.MALE)
.collect(Collectors.toList());
// 原列表不變,若需原地修改:personList.clear(); personList.addAll(filtered);
// ❌ 錯誤
for (String key : map.keySet()) {
if (condition) map.remove(key);
}
// ✅ 正確:Iterator + Entry
Iterator> it = map.entrySet().iterator();
while (it.hasNext()) {
if (condition) it.remove();
}
當集合僅有 1 個元素且被移除後,迭代器 hasNext() 直接回傳 false,結束迴圈,未再檢查 modCount,故不拋異常。不可依賴此行為。
| 方案 | 優點 | 缺點 | 推薦場景 |
|---|---|---|---|
| Iterator.remove() | 標準、語意清晰 | 需顯式迭代器 | 通用、教學 |
| 反向索引 | ArrayList 效能最好、無額外物件 | 僅適用 RandomAccess 列表 | 高效能、ArrayList |
| 收集後批次刪除 | 程式碼簡潔、邏輯分離 | 額外 O(K) 空間 | 業務邏輯複雜 |
| Stream filter | 函數式、不可變、易平行化 | 產生新列表、舊版本不支援 | Java 8+、新專案 |
遍歷時修改結構,必須透過迭代器自身的修改方法,或改用不修改原集合的替代策略。