foreach 是 iterator 的语法糖,编译后转为 hasnext() 和 next() 调用;遍历 arraylist 时三者性能几乎无差别;边遍历边删除必须用 iterator.remove();concurrenthashmap 的 iterator 具有弱一致性;禁止在 for 循环内重复创建 iterator。
foreach 就是 Iterator 的语法糖,别被表象骗了
Java 编译器会把 for (String s : list) 直接翻译成等效的 Iterator 调用:hasNext() + next()。字节码里根本不存在“foreach 指令”,它只是写法更简洁而已。所以性能上三者(for、foreach、手写 Iterator)在遍历 ArrayList 时几乎无差别——真正拖慢速度的,是开发者自己写的低效逻辑,比如在循环体内反复调用 list.iterator() 或每次迭代都查 list.size()。
边遍历边删元素,只有 Iterator.remove() 是安全的
用 for 循环遍历时调 list.remove(i) 或 list.remove(obj),大概率会漏删、重复删或抛 IndexOutOfBoundsException;用 foreach 直接删会触发 ConcurrentModificationException——因为它的底层 Iterator 检测到 modCount 被外部修改了。唯一安全的方式是:
- 拿到
Iterator实例后,只调用它的remove()方法(必须在next()之后调用) - 不能在
next()前或连续两次调remove(),否则抛IllegalStateException
示例:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("target".equals(s)) it.remove(); // ✅ 安全
}
并发读多写少?Iterator 的“弱一致性”不是 bug 是设计
ConcurrentHashMap 的 keySet().iterator()、values().iterator() 全部是弱一致的:它不阻塞写操作,也不被写操作阻塞,遍历时可能看到部分更新、看不到新增、甚至跳过刚删除的项。这不是缺陷,而是为高吞吐读场景做的取舍。如果你需要强一致性(比如导出快照),得换方式: