在Java集合操作中,删除元素是高频需求,但错误的删除方式很容易引发ConcurrentModificationException异常,影响程序正常运行。下面介绍几种安全的集合元素删除方法。

直接使用集合remove方法的问题
如果在遍历集合的过程中直接调用集合的remove(Object o)或者remove(int index)方法,会修改集合的修改次数,而遍历器在遍历时会检查修改次数是否和预期一致,不一致就会抛出异常。
以下是错误示例:
import java.util.ArrayList;
import java.util.List;
public class WrongDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 遍历时直接调用集合的remove方法,会触发ConcurrentModificationException
for (String s : list) {
if ("b".equals(s)) {
list.remove(s);
}
}
}
}
使用Iterator迭代器删除元素
Iterator是集合的专用遍历工具,它自带的remove()方法会在删除元素后同步更新修改次数,不会触发异常,是最传统的集合安全删除方式。
使用示例:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 获取集合的迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if ("b".equals(s)) {
// 调用迭代器的remove方法删除元素,安全无异常
iterator.remove();
}
}
System.out.println(list); // 输出 [a, c]
}
}
注意:使用Iterator删除时,必须先调用next()方法获取到元素,才能调用remove()方法,否则会抛出IllegalStateException。
使用removeIf方法删除(Java8及以上)
Java8为集合接口新增了removeIf(Predicate<? super E> filter)方法,可以直接传入过滤条件删除符合条件的元素,内部已经封装了安全的删除逻辑,使用起来非常简洁。
使用示例:
import java.util.ArrayList;
import java.util.List;
public class RemoveIfDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 传入lambda表达式作为过滤条件,删除所有等于b的元素
list.removeIf(s -> "b".equals(s));
System.out.println(list); // 输出 [a, c]
}
}
该方法不仅适用于List,也适用于Set等其他实现了Collection接口的集合,适用场景非常广泛。
复制集合副本再删除
如果不想修改原集合的遍历逻辑,也可以先复制一份集合的副本,遍历副本的同时删除原集合中的对应元素,这种方式也能避免并发修改异常。
使用示例:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class CopyDeleteDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
// 复制一份集合副本用于遍历
Set<String> copySet = new HashSet<>(set);
for (String s : copySet) {
if ("b".equals(s)) {
// 删除原集合中的元素,遍历的是副本,不会触发异常
set.remove(s);
}
}
System.out.println(set); // 输出 [a, c]
}
}
这种方式的缺点是会额外占用一份集合副本的内存,如果集合数据量非常大,需要考虑内存开销问题。
不同方法的适用场景对比
以下是几种删除方法的对比,方便开发者根据场景选择:
| 删除方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Iterator.remove() | 所有Java版本,遍历过程中需要逐个判断删除的场景 | 兼容性好,逻辑清晰 | 代码相对繁琐,需要手动处理迭代逻辑 |
| removeIf() | Java8及以上版本,批量按条件删除的场景 | 代码简洁,一行即可完成删除 | 依赖Java8及以上版本 |
| 复制副本删除 | 不想修改原有遍历逻辑,或者集合类型不支持Iterator的场景 | 逻辑简单,无需关注遍历细节 | 额外占用内存,大数据量时开销大 |
注意事项
- 不管使用哪种删除方式,都要明确删除的元素范围,避免误删数据。
- 如果是多线程场景下操作集合,还需要额外考虑线程安全问题,上述方法仅适用于单线程场景,多线程场景需要使用并发集合或者加锁处理。
- 对于不可变集合,本身不支持删除操作,调用删除方法会直接抛出异常,需要先确认集合是否可修改。
Java集合删除IteratorConcurrentModificationExceptionremove修改时间:2026-06-15 10:27:28