ListIterator 是 Java 集合框架中一个功能强大的迭代器,专为 List 接口设计。它扩展了 Iterator 接口,提供了双向遍历和更多操作功能。
Java ListIterator 接口详解
1. 基本特点
java
public interface ListIterator<E> extends Iterator<E> {
// 新增的方法
boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
void set(E e);
void add(E e);
// 继承自 Iterator
boolean hasNext();
E next();
void remove();
}
2. 获取 ListIterator 对象
java
import java.util.*;
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
// 获取 ListIterator
ListIterator<String> iterator = list.listIterator(); // 从开头
ListIterator<String> iterator2 = list.listIterator(2); // 从索引2开始
3. 核心方法详解
遍历方法
java
List<String> list = new ArrayList<>(Arrays.asList("Java", "Python", "C++"));
ListIterator<String> it = list.listIterator();
// 正向遍历
while (it.hasNext()) {
System.out.println(it.next() + " [index: " + it.nextIndex() + "]");
// 输出: Java [index: 1], Python [index: 2], C++ [index: 3]
}
// 反向遍历
while (it.hasPrevious()) {
System.out.println(it.previous() + " [previous index: " + it.previousIndex() + "]");
// 输出: C++ [previous index: 1], Python [previous index: 0], Java [previous index: -1]
}
修改方法
java
List<String> languages = new ArrayList<>(Arrays.asList("Java", "Python", "JavaScript"));
ListIterator<String> it = languages.listIterator();
// 替换元素
it.next(); // 移动到 "Java"
it.set("Java SE"); // 替换当前元素
// 添加元素
it.next(); // 移动到 "Python"
it.add("C++"); // 在 "Python" 之前添加
// 现在列表: ["Java SE", "C++", "Python", "JavaScript"]
// 删除元素
it.next(); // 移动到 "Python"
it.remove(); // 删除 "Python"
4. 使用示例
示例1:双向遍历和修改
java
public class ListIteratorExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ListIterator<Integer> it = numbers.listIterator();
// 正向遍历并加倍奇数
while (it.hasNext()) {
int num = it.next();
if (num % 2 != 0) {
it.set(num * 2);
}
}
System.out.println("修改后: " + numbers); // [2, 2, 6, 4, 10]
// 反向遍历并插入元素
while (it.hasPrevious()) {
int index = it.previousIndex();
int num = it.previous();
if (index % 2 == 0) {
it.add(num * 10); // 在偶数索引位置插入
}
}
System.out.println("最终结果: " + numbers);
// [20, 2, 2, 60, 6, 4, 100, 10]
}
}
示例2:列表反转
java
public class ListReverser {
public static <T> void reverse(List<T> list) {
ListIterator<T> forward = list.listIterator();
ListIterator<T> backward = list.listIterator(list.size());
for (int i = 0, mid = list.size() / 2; i < mid; i++) {
T temp = forward.next();
forward.set(backward.previous());
backward.set(temp);
}
}
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
reverse(list);
System.out.println(list); // [E, D, C, B, A]
}
}
5. 重要规则和注意事项
调用顺序规则:
java
ListIterator<String> it = list.listIterator();
// 错误示例(会抛出 IllegalStateException)
it.remove(); // × 没有调用 next() 或 previous()
it.set("X"); // × 没有调用 next() 或 previous()
// 正确使用
it.next(); // √
it.remove(); // √ 可以调用
it.next(); // √
it.set("X"); // √ 可以调用
it.add("Y"); // √ 随时可以调用
// 注意:add() 后不能立即调用 remove() 或 set()
并发修改检查:
java
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
ListIterator<String> it1 = list.listIterator();
ListIterator<String> it2 = list.listIterator();
it1.next();
it1.add("X"); // 通过 it1 修改列表
// it2.next(); // 会抛出 ConcurrentModificationException
// 因为列表被其他迭代器修改了
6. 与 Iterator 的比较
| 特性 | Iterator | ListIterator |
|---|---|---|
| 遍历方向 | 单向(向前) | 双向(向前/向后) |
| 遍历时修改 | 只能删除 | 添加、删除、替换 |
| 获取索引 | 不支持 | 支持(nextIndex(), previousIndex()) |
| 适用范围 | 所有 Collection | 仅 List |
| 起始位置 | 只能从开头 | 可以指定起始位置 |
7. 性能考虑
-
对于 ArrayList: ListIterator 提供 O(1) 的访问时间
-
对于 LinkedList: 需要小心使用,频繁的 previous() 调用可能影响性能
-
内存占用: 每个 ListIterator 需要维护当前位置和修改计数
总结
ListIterator 是处理 List 集合最强大的工具之一,特别适合需要:
-
双向遍历
-
遍历时修改(添加、删除、替换)
-
需要知道当前位置索引
-
实现复杂列表算法
关键要点:
-
始终检查
hasNext()/hasPrevious()避免异常 -
注意
add()、remove()、set()的调用顺序限制 -
理解并发修改的约束
-
合理使用索引定位功能