贝利信息

在Java里如何安全地遍历集合_Java集合遍历安全策略说明

日期:2025-12-09 00:00 / 作者:P粉602998670
Java安全遍历集合需规避ConcurrentModificationException和NullPointerException,优先用增强for循环(只读)、Iterator.remove()(边遍历边删)、线程安全集合或同步块(多线程)、Stream无副作用操作(函数式)。

在Java中安全遍历集合,核心是避免并发修改异常(ConcurrentModificationException)空指针异常(NullPointerException),同时兼顾线程安全与性能。关键不在于“能不能遍历”,而在于“用什么方式、在什么场景下遍历最稳妥”。

优先使用增强for循环(但注意不可删除元素)

增强for循环(for-each)底层调用Iterator,语法简洁、可读性高,适用于只读遍历场景。

示例:

List list = getNames();
if (list != null) {
  for (String name : list) {
    System.out.println(name);
  }
}

需要边遍历边删除?必须用显式Iterator.remove()

这是唯一被JDK明确支持的“遍历时安全删除”方式,Iterator的remove()方法会同步更新内部modCount,避免校验失败。

示例:

Iterator it = list.iterator();
while (it.hasNext()) {
  String s = it.next();
  if (s.startsWith("A")) {
    it.remove(); // 安全删除
  }
}

多线程环境?选线程安全集合或加锁

普通ArrayList、HashMap等非线程安全,多线程读写+遍历极易出问题。不能靠“遍历方式”解决,得从数据结构或同步机制入手。

正确示例(同步块):

synchronized (list) {
  for (String s : list) {
    process(s);
  }
}

函数式遍历(Stream)需留意短路与副作用

Java 8+ 的Stream.forEach()看起来简洁,但默认不保证顺序(并行流),且禁止在lambda中修改外部集合状态。

推荐替代写法:

List filtered = list.

stream()
  .filter(s -> !s.isEmpty())
  .collect(Collectors.toList());

基本上就这些。安全不是靠某一种写法包打天下,而是根据是否修改、是否多线程、是否允许延迟计算,选对工具链。判空、用对迭代器、分清集合类型——三者到位,遍历就很难翻车。