集合遍历方式
集合遍历方式
选择遍历方式时,要看是否需要索引、删除元素、提前结束、保持顺序或完成筛选与聚合。
Iterator
Iterator 是 Collection 的通用遍历方式。迭代器维护游标,必须获取一次后复用。
代码块收起展开
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}- hasNext():是否还有下一个元素。
- next():返回元素并推进游标;越界时抛出 NoSuchElementException。
- remove():删除最近一次由 next() 返回的元素。
不要在每次判断时重新调用 names.iterator(),否则会不断获得从头开始的新迭代器。
遍历时删除
代码块收起展开
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
if (iterator.next().isBlank()) {
iterator.remove();
}
}
names.removeIf(String::isBlank);增强 for 中直接调用原集合的 remove() 通常触发 ConcurrentModificationException。它是快速失败检查,不是线程安全保证。
增强 for
代码块收起展开
for (String name : names) {
System.out.println(name);
}适合数组和实现 Iterable 的对象。对集合而言,底层仍使用迭代器。支持 break、continue 和 return,但没有天然索引,也不适合直接删除原集合元素。
普通 for
适合数组和支持随机访问的 ArrayList。LinkedList#get(i) 每次可能线性查找,索引遍历会退化为 $O(n^2)$,应使用迭代器或增强 for。
forEach
代码块收起展开
names.forEach(System.out::println);
names.forEach(name -> System.out.println(name.trim()));适合简单逐项操作。Lambda 中不能像循环一样直接 break 或 continue,复杂控制流应使用普通循环。
Stream
代码块收起展开
List<String> result = names.stream()
.filter(name -> !name.isBlank())
.map(String::trim)
.map(String::toUpperCase)
.toList();Stream 适合筛选、转换和聚合。并行流的 forEach 不保证遇到顺序;forEachOrdered 保持顺序但可能降低并行收益。Stream 终止后不能再次使用。
Map
需要键和值时优先 entrySet():
代码块收起展开
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() |