一、Iterator 迭代器接口
1. 基础说明
- 包:
java.util.Iterator,使用前需要导入 - 作用:通用遍历 Collection 集合,依靠指针(游标)跟踪元素
- 游标初始位置:第一个元素的前面
- 泛型说明:不写泛型时,取出元素默认是
Object类型,需要强制类型转换;推荐使用泛型,避免强转
2. 核心方法
| 方法 | 功能描述 |
|---|---|
boolean hasNext() |
判断游标后面是否还有下一个元素;只判断,不移动指针 |
E next() |
返回下一个元素,同时将指针向后移动一位 |
void remove() |
删除迭代器最后访问到的元素(迭代器自带删除) |
遍历流程(课件图示顺序) ① hasNext () 判断有元素 → ② next () 取值 + 指针后移 ③ hasNext () 判断有元素 → ④ next () 取值 + 指针后移 ⑤ hasNext () 判断有元素 → ⑥ next () 取值 + 指针后移 ⑦ hasNext () 判断无元素,循环结束
3. 基础代码示例
import java.util.ArrayList;
import java.util.Iterator;
public class TestIterator {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
4. 重点:并发修改异常 ConcurrentModificationException
✅ 课件要点:迭代器遍历期间,如果调用**集合对象自己的 remove ()/add ()**修改集合长度,继续遍历就抛出并发修改异常
-
错误写法(集合 remove)
while (it.hasNext()){
String s = it.next();
if("李四".equals(s)){
list.remove(s); // ❌ 集合方法,报异常
}
} -
正确写法(迭代器自带 remove)
while (it.hasNext()){
String s = it.next();
if("李四".equals(s)){
it.remove(); // ✅ 迭代器删除,安全
}
}
原理:集合维护modCount修改计数器,迭代器记录初始值expectedModCount,两者不一致触发异常。
5. Iterator 局限
只能单向向后遍历;没有添加、替换元素的方法;只能用于 Collection。
二、ListIterator(List 专属迭代器,Iterator 的子接口)
只用于 List 集合,功能比普通 Iterator 更强,支持双向遍历、增删改、获取索引
1. 主要特性
- 双向遍历:可以向前、向后遍历
- 修改能力:遍历中添加、删除、替换元素
- 索引支持:可以获取当前元素对应索引
2. 全套方法表
| 方法 | 描述 |
|---|---|
next() |
返回下一个元素,光标后移 |
previous() |
返回前一个元素,光标前移 |
hasNext() |
判断是否存在下一个元素 |
hasPrevious() |
判断是否存在前一个元素 |
nextIndex() |
返回下一个元素的索引 |
previousIndex() |
返回前一个元素的索引 |
remove() |
删除光标前的元素 |
set(E e) |
替换光标前的元素 |
add(E e) |
在光标当前位置插入元素 |
3. 简单示例(反向遍历)
import java.util.ArrayList;
import java.util.ListIterator;
public class TestListIterator {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
ListIterator<String> lit = list.listIterator();
// 先走到末尾
while (lit.hasNext()){
lit.next();
}
// 反向遍历
while (lit.hasPrevious()){
System.out.println(lit.previous());
}
}
}
三、foreach 循环(增强 for 循环)
1. 基础介绍
foreach 是简化版 for 循环,底层依然是 Iterator 迭代器(语法糖) 适用范围:数组、所有实现Iterable的 Collection 集合 语法格式:
for(容器中元素类型 临时变量 : 容器变量) {
执行语句
}
示例:
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for(String s : list){
System.out.println(s);
}
int[] arr = {1,2,3};
for(int num : arr){
System.out.println(num);
}
2. 课件重点缺陷
foreach 循环只能访问元素,不能修改集合结构(增删);循环里的临时变量是元素副本:
- 修改临时变量,不会改变原集合 / 数组里面的值
- 遍历途中调用集合 add/remove → 并发修改异常
- 没有索引,不知道当前遍历位置
四、四种遍历方式汇总对比(Iterator / ListIterator / 增强 for / Lambda forEach)
| 遍历方式 | 底层 | 方向 | 增删改 | 是否有索引 | 适用场景 |
|---|---|---|---|---|---|
| Iterator | 迭代器 | 单向向后 | ✅ it.remove() | ❌ | 通用 Collection,遍历中删除 |
| ListIterator | List 专属迭代器 | 双向 | ✅ add/remove/set | ✅ | List 集合,反向遍历、边遍历边修改 |
| 增强 for foreach | Iterator 语法糖 | 单向向后 | ❌ 不能增删集合 | ❌ | 单纯遍历,代码简洁 |
| 集合.forEach (Lambda) | 函数式接口 | 单向 | ❌ 不能增删集合 | ❌ | JDK8+,简洁对每个元素执行操作 |
五、易错点总结
hasNext()只判断,不移动指针;不能连续多次调用next(),容易NoSuchElementException- 泛型缺失时,Iterator 取出元素是 Object,需要强制转换
- ListIterator只能 List 获取,Set 集合不能使用
- 增强 for 只是语法糖,编译后依然变成 Iterator,同样不能在遍历时直接调用集合增删方法