集合遍历方式

集合遍历方式

选择遍历方式时,要看是否需要索引、删除元素、提前结束、保持顺序或完成筛选与聚合。

Iterator

Iterator 是 Collection 的通用遍历方式。迭代器维护游标,必须获取一次后复用。

代码块JAVA · 5 行收起展开
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
    String name = iterator.next();
    System.out.println(name);
}
  • hasNext():是否还有下一个元素。
  • next():返回元素并推进游标;越界时抛出 NoSuchElementException。
  • remove():删除最近一次由 next() 返回的元素。

不要在每次判断时重新调用 names.iterator(),否则会不断获得从头开始的新迭代器。

遍历时删除

代码块JAVA · 8 行收起展开
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
    if (iterator.next().isBlank()) {
        iterator.remove();
    }
}

names.removeIf(String::isBlank);

增强 for 中直接调用原集合的 remove() 通常触发 ConcurrentModificationException。它是快速失败检查,不是线程安全保证。

增强 for

代码块JAVA · 3 行收起展开
for (String name : names) {
    System.out.println(name);
}

适合数组和实现 Iterable 的对象。对集合而言,底层仍使用迭代器。支持 break、continue 和 return,但没有天然索引,也不适合直接删除原集合元素。

普通 for

适合数组和支持随机访问的 ArrayList。LinkedList#get(i) 每次可能线性查找,索引遍历会退化为 $O(n^2)$,应使用迭代器或增强 for。

forEach

代码块JAVA · 2 行收起展开
names.forEach(System.out::println);
names.forEach(name -> System.out.println(name.trim()));

适合简单逐项操作。Lambda 中不能像循环一样直接 break 或 continue,复杂控制流应使用普通循环。

Stream

代码块JAVA · 5 行收起展开
List<String> result = names.stream()
        .filter(name -> !name.isBlank())
        .map(String::trim)
        .map(String::toUpperCase)
        .toList();

Stream 适合筛选、转换和聚合。并行流的 forEach 不保证遇到顺序;forEachOrdered 保持顺序但可能降低并行收益。Stream 终止后不能再次使用。

Map

需要键和值时优先 entrySet():

代码块JAVA · 5 行收起展开
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

scores.forEach((name, score) -> System.out.println(name + " = " + score));
需求推荐方式
通用只读遍历增强 for
遍历时删除Iterator / removeIf()
需要索引普通 for
筛选、映射、聚合Stream
简单逐项操作forEach
Map 的键和值entrySet() / Map.forEach()

延伸阅读