侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

ArrayList 的遍历与元素删除

2025-12-13 / 0 评论 / 4 阅读

题目

ArrayList 的遍历与元素删除

信息

  • 类型:问答
  • 难度:⭐

考点

ArrayList遍历,迭代器使用,并发修改异常

快速回答

在遍历 ArrayList 时安全删除元素的方法:

  • 使用 Iterator 的 remove() 方法可避免 ConcurrentModificationException
  • 或使用 for 循环倒序遍历删除防止索引错位
  • 禁止在 foreach 循环中直接调用 ArrayList 的 remove()
## 解析

问题背景

在 Java 中直接使用 foreach 循环或迭代器遍历 ArrayList 时调用 remove() 删除元素,会抛出 ConcurrentModificationException。这是因为集合的结构被意外修改导致遍历状态不一致。

原理说明

ArrayList 内部维护一个 modCount(修改计数器)。当创建迭代器时,会记录当前 modCount 值。每次遍历会检查该值是否变化,若变化则抛出异常。直接调用集合的 remove() 会使 modCount++,但迭代器不知情。

正确做法与代码示例

方法 1:使用 Iterator.remove()

ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if ("B".equals(item)) {
        iterator.remove(); // 安全删除
    }
}
// 结果:[A, C]

方法 2:倒序 for 循环

for (int i = list.size() - 1; i >= 0; i--) {
    if ("B".equals(list.get(i))) {
        list.remove(i); // 倒序删除不影响索引
    }
}

常见错误

  • foreach 循环中直接删除
    for (String s : list) { list.remove(s); } → 抛出异常
  • 正序 for 循环删除
    for (int i=0; i<list.size(); i++) { list.remove(i); } → 漏删元素(删除后索引前移)

最佳实践

  • 优先使用 Iterator.remove(),它是集合框架的标准安全操作
  • Java 8+ 推荐:list.removeIf(item -> "B".equals(item));
  • 若需在遍历时同时删除/添加,考虑使用 CopyOnWriteArrayList

扩展知识

  • ConcurrentModificationException 机制:所有 fail-fast 集合(如 ArrayList、HashMap)都通过 modCount 检测并发修改
  • Java 8+ 简化操作
    removeIf(Predicate) 内部使用迭代器实现,代码更简洁
  • 替代方案:需要频繁增删时,可考虑 LinkedList(但迭代器删除仍是首选)