在 java 中循环删除元素时,最稳妥且不易出错的做法是使用 iterator 的 remove() 方法。直接调用集合的 remove() 方法会破坏迭代器的内部状态,导致 concurrentmodificationexception 或跳过相邻元素;而使用增强 for 循环(foreach)底层也是依赖迭代器,因此同样不能安全地执行删除操作。

为什么 foreach 和索引循环会漏删或报错
这两种方式之所以出问题,是因为它们在删除元素后没有正确处理索引或迭代器的游标位置。增强 for 循环在每次迭代时会检查集合的修改计数(modCount),一旦发现与预期不符就会抛出异常。普通 for 循环如果使用正向遍历并删除元素,会导致后续元素的索引前移,从而跳过被删除元素后面的那个元素。例如,删除索引为 0 的元素后,原索引为 1 的元素变成了新的索引 0,但循环变量 i 却增加到了 1,导致漏删。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SafeRemoveExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));
// 使用 Iterator 安全删除
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if (item.equals("B")) {
it.remove(); // 安全删除
}
}
System.out.println(list); // 输出: [A, C, D]
}
}
如何正确使用反向索引遍历进行删除
如果你必须使用索引(例如需要访问下标),可以采用从后往前遍历的方式。因为删除当前索引的元素只会影响比它大的索引,而不会影响比它小的索引,所以反向遍历可以避免索引错位导致的漏删问题。这种方式适用于你不需要频繁移动大量数据且对性能有特定要求的场景,但在大多数情况下,Iterator 依然是首选。
立即学习“Java免费学习笔记(深入)”;

import java.util.ArrayList;
import java.util.List;
public class ReverseIndexRemoveExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));
// 从后往前遍历,避免索引错位
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i).equals("B")) {
list.remove(i); // 安全删除
}
}
System.out.println(list); // 输出: [A, C, D]
}
}
基于程序中某个输入、条件或结果的具体问题
在上述代码中,当输入列表包含多个连续匹配的元素(如 ["A", "B", "B", "C"])时,Iterator 的 remove() 方法能正确移除所有匹配项,而正向索引循环则会漏掉第二个 "B"。这是因为 Iterator 在调用 next() 后记录当前位置,remove() 仅移除该位置元素并重置迭代器状态,不会干扰下一次 hasNext() 的判断。而正向索引循环在删除第一个 "B" 后,列表长度减一,但索引 i 仍递增,导致原本位于索引 2 的第二个 "B" 被跳过。


















