Iterator遍历必须先hasNext()再next():前者探路不移动指针,后者取值并移动;删除只能用it.remove()且须在next()后立即调用,否则抛异常。

Java 中 Iterator 的 hasNext() 和 next() 必须严格配合使用:先用 hasNext() 探路,确认有元素后再用 next() 取值。跳过判断直接调用 next() 会抛 NoSuchElementException;在条件中连写 it.next() != null 不仅逻辑错误,还可能跳过元素或引发空指针。
标准写法:while 循环里只放 hasNext() 做条件
这是最安全、最通用的模式,适用于所有 Collection 类型(List、Set、Map 视图等):
-
hasNext()不改变迭代器状态,只返回true或false -
next()才真正移动指针并返回当前元素,每次调用都消耗一个元素 - 每个
next()都必须由一次hasNext()判断“担保”
示例:
Iterator<String> it = list.iterator();while (it.hasNext()) {
String s = it.next(); // ✅ 每次都在确认有元素后才取
System.out.println(s);
}
遍历时安全删除元素:只能用 it.remove()
想边遍历边删元素,绝不能调用 list.remove() 或 set.remove(),否则触发 ConcurrentModificationException。
立即学习“Java免费学习笔记(深入)”;
-
remove()只能删除上一次next()返回的那个元素 - 必须在调用
next()后立即调用,且每个next()最多配一次remove() - 不能在未调用
next()时调用remove(),会抛IllegalStateException
示例(删掉所有长度为 1 的字符串):
Iterator<String> it = list.iterator();while (it.hasNext()) {
String s = it.next();
if (s.length() == 1) {
it.remove(); // ✅ 正确删除方式
}
}
常见错误写法及原因
这些看似“省事”的写法实际隐藏严重风险:
-
在 while 条件里写
it.next() != null:next()已经取走元素,循环体里再调一次就跳过了;且next()不返回null(除非集合存了null),判空无意义 - 先 if (it.hasNext()) it.next(); 再进 while:开头多取一次,导致第一个元素被丢弃
-
连续调两次 next():
it.next(); it.next();—— 第二个很可能越界,抛异常 -
遍历完不重新获取迭代器就重用:迭代器不可复位,必须调
collection.iterator()拿新的
替代方案:for-each 是语法糖,不是替代逻辑
for (String s : list) 看似简单,但它底层就是编译器自动展开成 hasNext()/next() 的 while 循环。所以它遇到的异常(如 ConcurrentModificationException、ClassCastException)根源完全一致。
- 优势:简洁、不易手误、适合纯读取场景
- 限制:不支持删除、无法获取索引、不能跳过或提前中断多个元素
- 本质:只是封装,不是绕过规则——该检查的还是要检查,该守的边界一个都不能少


















