java 中 iterator 和 for-each 的核心区别在于控制粒度:for-each 是语法糖,底层依赖 iterator 实现,但隐藏了迭代细节且无法在循环中安全移除元素;iterator 允许在遍历时调用 remove() 方法修改集合结构,并支持显式的 hasnext() 检查。若只需读取数据,优先使用 for-each 以获得更简洁的代码;若需在遍历过程中过滤或移除元素,必须使用 iterator。

for-each 编译后的实际形态是什么
for-each 循环在编译期会被转换为对 Iterable 接口的 iterator() 方法的调用,随后通过 hasNext() 和 next() 完成遍历。这意味着 for-each 并不直接操作集合索引,而是完全委托给 Iterator 接口。对于实现了 List 的类(如 ArrayList),编译器会生成基于索引的优化版本,但对于非随机访问的集合或通用 Iterable,它始终回退到标准的 Iterator 模式。这种转换使得代码更简洁,但也剥夺了开发者在循环内部干预迭代过程的能力。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ForEachDemo {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
// 使用 for-each
for (String item : list) {
System.out.println(item);
}
}
}</string>
预期输出:
A
B
C
遍历时如何安全地移除元素
在遍历集合时直接调用集合的 remove() 方法会触发 ConcurrentModificationException,因为集合的内部修改计数器(modCount)与 Iterator 的预期值不一致。要安全移除元素,必须使用 Iterator 提供的 remove() 方法。该方法会在删除当前元素后同步更新 modCount,从而保持迭代器的状态一致。这是 for-each 循环无法做到的,因为 for-each 循环隐式获取了 Iterator,但并未暴露该实例供开发者调用其 remove() 方法。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorRemoveDemo {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if ("B".equals(item)) {
it.remove(); // 安全移除
}
}
System.out.println(list); // [A, C]
}
}</string></string>
预期输出:
[A, C]
当集合为空时 next() 的行为差异
当集合中没有更多元素时,Iterator 的 next() 方法会抛出 NoSuchElementException,而 for-each 循环通过内部的 hasNext() 检查避免了直接调用 next(),因此不会抛出异常。在使用 Iterator 手动遍历时必须先调用 hasNext() 进行判断,否则一旦集合为空或已遍历完毕,直接调用 next() 将导致运行时错误。这一行为差异要求在使用 Iterator 时保持严格的条件检查习惯,而在 for-each 中则由编译器自动处理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











