ListIterator 是 List 专属双向迭代器,支持前后遍历及遍历时安全增删改元素;它维护游标位置,提供 next/previous、hasNext/hasPrevious、set/add/remove 等方法,功能强于普通 Iterator。

ListIterator 是 Java 中 List 接口提供的专属迭代器,它支持**双向遍历**(向前、向后),也支持在遍历过程中**安全地添加、删除、替换元素**——这是普通 Iterator 不具备的能力。
支持双向遍历:用 hasPrevious() / previous() 和 hasNext() / next()
不同于 Iterator 只能单向调用 next(),ListIterator 维护一个“游标位置”,初始在索引 0 之前。你可以:
- 调用
next()向后移动,获取当前游标后一个元素(类似传统遍历) - 调用
previous()向前移动,获取当前游标前一个元素(实现反向遍历) - 用
hasNext()判断后面是否还有元素,用hasPrevious()判断前面是否还有元素 - 游标位置始终介于两个元素之间(或首尾外侧),
nextIndex()返回下一个next()的索引,previousIndex()返回下一个previous()的索引
示例:从后往前打印列表
List<String> list = Arrays.asList("a", "b", "c");
ListIterator<String> lit = list.listIterator(list.size()); // 游标起始在末尾
while (lit.hasPrevious()) {
System.out.println(lit.previous()); // 输出 c, b, a
}
遍历时修改元素:set()、add()、remove() 都是安全的
ListIterator 允许在一次 next() 或 previous() 调用之后,立刻调用以下方法,且不会抛 ConcurrentModificationException:
立即学习“Java免费学习笔记(深入)”;
-
set(E e):替换上一次next()或previous()返回的元素(必须已调用过一次next()或previous(),否则抛IllegalStateException) -
add(E e):在游标当前位置插入新元素(插入后,新元素成为previous()的目标,原next()元素索引+1) -
remove():删除上一次next()或previous()返回的元素(同样要求已调用过取值操作,且不能连续调两次remove())
注意:这些操作直接作用于底层 List,会实时反映在列表中,且迭代器状态自动同步。
List<Integer> nums = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
ListIterator<Integer> lit = nums.listIterator();
while (lit.hasNext()) {
Integer val = lit.next();
if (val == 2) {
lit.set(20); // 替换 2 → 20
lit.add(25); // 在 20 后插入 25
}
}
// nums 变为 [1, 20, 25, 3, 4]
和普通 Iterator 的关键区别
普通 Iterator 只能单向遍历,且仅支持 remove()(还要求刚调用过 next());而 ListIterator:
- 必须由
List实例创建(list.listIterator()),Collection或数组无法使用 - 可双向移动,适合需要回溯、局部重读的场景(如解析器、编辑器光标)
- 修改能力更强:
add()和set()是独有的,remove()行为更灵活(支持previous()后删除) - 提供索引查询:通过
nextIndex()和previousIndex()获取逻辑位置,便于与 List 索引操作配合
使用注意事项
虽然功能强大,但需留意:
- 不能对非
List实现(如Set、Queue)调用listIterator()—— 它们没有该方法 -
set()和remove()必须紧跟在next()或previous()之后,中间不能穿插其他修改操作 -
add()后,再次调用next()会跳过新元素(因为游标已移到它后面),而previous()会立即返回它 - 并发修改仍不安全:多线程同时用同一个
ListIterator操作,或一个线程用迭代器、另一个直接调list.add(),仍可能出错


















