在Java里如何遍历ArrayList集合_Java集合遍历方法说明

for-each循环遍历ArrayList最安全,因其底层使用It

erator、语法简洁且自动避免索引越界和ConcurrentModificationException(前提是遍历时不修改集合);但删改操作、Stream惰性求值及混用Iterator.remove()与list.remove()易引发问题。

用 for-each 循环遍历 ArrayList 最安全

绝大多数情况下,直接用 for-each 是首选。它底层调用 Iterator,语法简洁,且自动规避了手动管理索引和并发修改异常(ConcurrentModificationException)的风险——前提是遍历时不修改集合本身。

常见错误现象:有人写 for (int i = 0; i 然后在循环体里调用 list.remove(i),结果漏删、越界或抛出异常。

实操建议:

  • 只读遍历 → 无脑用 for (String s : list)
  • 需要索引 → 改用传统 for 循环,但避免在循环中增删元素
  • 要边遍历边删除 → 必须用 Iterator.remove(),不能用 list.remove()

用 Iterator 遍历时删除元素的唯一正确方式

ArrayListIterator 是 fail-fast 的,一旦检测到结构被外部修改(比如调用 list.remove()),下一次调用 next()hasNext() 就会抛 ConcurrentModificationException。但 Iterator.remove() 是特例,它是被允许的唯一安全删除方式。

示例:

Iterator it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (s.startsWith("A")) {
        it.remove(); // ✅ 正确
    }
}

错误写法:

for (String s : list) {
    if (s.startsWith("A")) {
        list.remove(s); // ❌ 抛 ConcurrentModificationException
    }
}

用 ListIterator 反向遍历或双向操作

当需要从后往前遍历,或在遍历中插入元素(不只是删除),ListIterator 比普通 Iterator 更合适。它支持 hasPrevious()previous()add()set()

注意点:

  • ListIterator 只能用于 List 实现类(如 ArrayList),不能用于 SetMap
  • add() 插入后,新元素会被后续的 next() 跳过,但会被 previous() 立即看到
  • 创建时可指定起始索引:list.listIterator(list.size()) 表示从末尾开始反向遍历

Stream API 遍历适合函数式过滤/映射场景

Java 8+ 引入的 stream() 不是传统“遍历”,而是声明式处理。它适合做过滤、转换、聚合,但不适合需要精确控制流程(如 break、continue)或依赖索引顺序副作用的操作。

性能影响:

  • 小数据量(
  • 大数据量 + 多次中间操作(如多次 filter)可能比传统循环稍慢,因有对象创建和函数调用开销
  • 并行流(parallelStream())仅在 CPU 密集型、无状态操作中才有收益,对 I/O 或含同步逻辑的场景反而更差

示例(只读 + 过滤):

list.stream()
    .filter(s -> s.length() > 3)
    .forEach(System.out::println);
遍历看似简单,但删改逻辑、fail-fast 机制、迭代器状态、Stream 的惰性求值这些细节,一不留神就踩坑。尤其在多线程或嵌套循环里,Iterator.remove()list.remove() 的混用是最常被忽略的陷阱。