for-each能遍历数组(含基本类型)和实现了Iterable接口的类(如ArrayList、HashSet等);Map本身不可遍历,需用entrySet()、keySet()或values();遍历时修改集合会抛ConcurrentModificationException。

Java中的for-each循环(增强型for)只能用于实现了Iterable接口的集合或数组,不能直接遍历Map本身,也不能在遍历时安全地删除元素。
for-each能遍历哪些类型?
它底层调用的是Iterator,因此要求目标必须满足以下任一条件:
- 是数组(任何类型,包括基本类型数组)
- 是实现了
Iterable接口的类,如ArrayList、HashSet、LinkedList、LinkedHashMap等 - 自定义类显式实现
Iterable并提供iterator()方法
常见误用:Map不是Iterable,所以for (Entry e : map)会编译失败;必须用map.entrySet()、map.keySet()或map.values()之一。
遍历Map时的三种正确写法
因为Map本身不支持for-each,但它的三个视图都实现了Iterable:
立即学习“Java免费学习笔记(深入)”;
Mapmap = new HashMap<>(); map.put("a", 1); map.put("b", 2); // ✅ 遍历键值对 for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } // ✅ 遍历键 for (String key : map.keySet()) { System.out.println("key: " + key); } // ✅ 遍历值 for (Integer value : map.values()) { System.out.println("value: " + value); }
注意:entrySet()返回的是Set,不是List,所以顺序不保证(除非用LinkedHashMap)。
for-each中修改集合会抛ConcurrentModificationException
这是最容易踩的坑:在for-each循环体内调用list.remove()或set.add()等结构性修改操作,会导致运行时异常。
- 原因:
for-each隐式使用Iterator,而其checkForComodification()机制会检测modCount变化 - 替代方案:显式使用
Iterator并调用iterator.remove() - 若需添加元素,必须跳出循环后操作,或改用传统
for索引循环(仅适用于List)
错误示例:
Listlist = new ArrayList<>(Arrays.asList("a", "b", "c")); for (String s : list) { if ("b".equals(s)) { list.remove(s); // ⚠️ 抛 ConcurrentModificationException } }
性能与语义限制:什么时候不该用for-each
for-each简洁,但有明确边界:
- 需要访问当前索引(如“第几个元素”)→ 改用传统
for (int i = 0; i - 需要并行遍历多个集合 → 只能用索引或
Iterator手动控制 - 遍历过程中要移除多个匹配项 → 用
Iterator.remove()更安全清晰 - 对基本类型数组,
for-each无装箱开销,但若需修改原数组元素,则无效(因为遍历的是副本)
例如,想把int[]中每个数翻倍,for (int x : arr) { x *= 2; }完全不会改变arr内容——必须用索引赋值。









