Iterator 不支持遍历时直接修改元素,因其职责是安全遍历而非更新;正确方式是使用 ListIterator 的 set() 方法或先收集再批量修改。

Iterator 本身不支持直接修改正在遍历的元素,调用 iterator.next() 只能读取元素,不能赋值。试图用 list.get(i) = newValue 这类方式在迭代中修改,不仅与 Iterator 无关,还可能因并发修改导致异常或逻辑错误。
为什么不能边遍历边用索引改?
这不是语法限制,而是设计原则问题:Iterator 的核心职责是安全遍历,不是更新。若你在 for-each 或 while(iterator.hasNext()) 中,同时用 list.set(index, newValue) 修改底层集合,可能:
- 破坏迭代器的内部状态(如 ArrayList 的 modCount),触发
ConcurrentModificationException - 跳过或重复访问元素(尤其在删除/插入时)
- 逻辑混乱——遍历逻辑和修改逻辑混在一起,难以维护
正确修改方式:用 ListIterator(仅限 List)
ListIterator 是 Iterator 的子接口,专为 List 设计,支持双向遍历和修改:
-
set(E e):替换上一次next()或previous()返回的元素(必须先调用 next/previous) -
add(E e):在当前位置前插入新元素 -
remove():删除上一次返回的元素
示例:
立即学习“Java免费学习笔记(深入)”;
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
String s = lit.next();
if ("b".equals(s)) {
lit.set("B"); // ✅ 安全修改,不会抛 ConcurrentModificationException
}
}
// list 变为 ["a", "B", "c"]
通用方案:先收集索引/引用,再批量修改
适用于所有 Collection(Set、Map.values() 等不支持 ListIterator 的场景):
- 遍历过程中,只记录要修改的元素索引(List)或引用(对象本身)
- 遍历结束后,统一更新
示例(修改满足条件的对象字段):
List<Person> people = ...;
List<Person> toUpdate = new ArrayList<>();
for (Person p : people) {
if (p.getAge() < 18) {
toUpdate.add(p); // 记录引用
}
}
for (Person p : toUpdate) {
p.setStatus("minor"); // ✅ 安全修改对象状态
}
注意:这改的是对象属性,不是替换集合中的元素引用;若需替换整个元素(如把 Person 换成另一个对象),对 List 可用 list.set(index, newPerson),前提是遍历时已存好索引。
避免陷阱:别在增强 for 循环里增删元素
以下写法是错的:
for (String s : list) {
if ("x".equals(s)) {
list.remove(s); // ❌ 触发 ConcurrentModificationException
}
}
应改用:
-
Iterator.remove()(唯一安全的遍历时删除方式) - 或
ListIterator.set()+remove()组合 - 或倒序 for 循环(仅适用于 ArrayList 等支持随机访问的 List)


















