增强for循环是编译期语法糖,转为传统迭代器遍历;foreach()是运行时接口方法,由集合实现类决定逻辑,二者在异常处理、删除支持、性能及适用场景上存在差异。

增强for循环(for-each)和 Iterable.forEach() 在语义上相似,但底层机制不同:前者是语法糖,编译期转为传统迭代器遍历;后者是接口方法,运行时由实现类提供具体逻辑。
增强for循环的底层:编译期生成迭代器代码
Java中 for (T item : collection) 不是独立语法结构,而是编译器自动重写为标准迭代器模式:
- 调用
collection.iterator()获取Iterator实例 - 用
hasNext()判断是否还有元素 - 每次循环调用
next()取值,并赋给循环变量
例如:for (String s : list) 编译后等价于:
while (it.hasNext()) {
String s = it.next();
// 循环体
}
forEach() 方法的底层:依赖具体实现的函数式遍历
Iterable.forEach(Consumer) 是一个默认方法,其行为由子类决定:
- ArrayList / LinkedList:内部仍用索引或指针顺序访问,但封装在 lambda 调用中
- HashSet / HashMap.KeySet:本质是遍历哈希桶数组 + 链表/红黑树,顺序不保证
- ConcurrentHashMap:可能分段遍历,支持并发安全,但不保证原子性或强一致性
关键点:它不强制使用 Iterator,也不一定触发 fail-fast 检查——比如某些集合实现可能绕过 modCount 校验。
两者的关键差异与注意事项
-
异常处理不同:增强for循环遇到
ConcurrentModificationException会立即抛出;而forEach()在部分并发集合中可能静默容忍结构修改 - 无法在遍历时删除元素:两者都不支持直接 remove(增强for无 remove 接口;forEach 的 Consumer 无法访问迭代器)
- 性能微差:forEach 多一层函数调用开销,但JVM通常能内联优化,实际差异可忽略
-
空集合安全:二者都对 null 集合抛
NullPointerException,需提前判空
何时选哪个?看场景需求
- 需要简洁遍历 + 明确控制流程(如中途 break、continue)→ 用增强for
- 配合 Stream 或函数式风格,或后续要链式调用 → 用 forEach
- 遍历自定义 Iterable 且已重写 forEach 提升性能(如跳过空桶)→ 优先 forEach
- 调试时需单步跟踪每一步 → 增强for 更直观;日志统一处理 → forEach 更集中









