listiterator是list专用的双向迭代器,支持前后遍历、索引获取及遍历中增删改操作;需通过list的listiterator()方法获取,不适用于set/map。

Java 中 ListIterator 是 Iterator 的子接口,专为 List 设计,支持双向遍历(向前、向后)、获取索引位置,以及在遍历过程中安全地添加、替换、删除元素。普通 Iterator 只能单向遍历且仅支持删除,而 ListIterator 提供了更灵活的操作能力。
如何获取 ListIterator 实例
必须通过 List 实现类(如 ArrayList、LinkedList)的 listIterator() 方法获取:
-
list.listIterator():从头开始(索引 0) -
list.listIterator(index):从指定索引位置开始(合法索引范围:0 到 list.size())
注意:Set、Map 等集合不支持 ListIterator;只有实现了 List 接口且支持随机访问或链式遍历的集合才提供该功能。
双向遍历:hasPrevious()/previous() 与 hasNext()/next()
ListIterator 维护一个“游标”位置(cursor),初始在第一个元素之前。每次调用 next() 后游标前移一位;调用 previous() 后游标后退一位。
-
hasNext()判断游标后是否有元素;next()返回游标后元素,并将游标移到该元素之后 -
hasPrevious()判断游标前是否有元素;previous()返回游标前元素,并将游标移到该元素之前 -
nextIndex()返回下一次next()将返回的元素索引(即游标当前位置) -
previousIndex()返回下一次previous()将返回的元素索引
示例:正向 + 反向交替遍历
List<string> list = new ArrayList(Arrays.asList("a", "b", "c"));
ListIterator<string> lit = list.listIterator();
// 正向走两步
if (lit.hasNext()) System.out.println(lit.next()); // a,游标在 a 后(索引1)
if (lit.hasNext()) System.out.println(lit.next()); // b,游标在 b 后(索引2)
// 转向反向
if (lit.hasPrevious()) System.out.println(lit.previous()); // b,游标回到 b 前(索引1)
if (lit.hasPrevious()) System.out.println(lit.previous()); // a,游标回到 a 前(索引0)</string></string>
遍历中安全修改列表元素
ListIterator 允许在遍历中执行以下操作,且不会引发 ConcurrentModificationException(前提是只通过它自身方法修改):
-
set(E e):替换上一次next()或previous()返回的元素(必须已调用过next()/previous(),且未被后续add()干扰) -
add(E e):在游标位置插入新元素,插入后游标位于新元素之后,原位置及后续元素索引全部+1 -
remove():删除上一次next()或previous()返回的元素(同set,需先有“上次调用”)
⚠️ 注意限制:
- 不能连续两次调用
remove()或set()(中间必须有一次next()或previous()) -
add()后不能再立即调用set()(因为没有“上一次返回的元素”) - 所有修改均直接作用于原列表,无需额外同步
示例:遍历时将偶数索引元素转为大写,并在 "b" 后插入 "x"
List<string> list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
ListIterator<string> lit = list.listIterator();
while (lit.hasNext()) {
String s = lit.next();
if (lit.nextIndex() % 2 == 0) { // 索引为偶数(注意 nextIndex() 是下一个元素的索引)
lit.set(s.toUpperCase());
}
if ("b".equals(s)) {
lit.add("x"); // 插入到 b 之后,即原索引1后 → 新列表:["a","b","x","c","d"]
}
}</string></string>
常见误区与注意事项
-
ListIterator不是线程安全的,多线程并发修改仍需外部同步 -
LinkedList的ListIterator遍历效率高(O(1) 前后移动),ArrayList的previous()在底层需计算索引,但仍是 O(1) - 不要混用
for-each循环(本质是普通Iterator)和ListIterator修改同一列表,容易触发并发修改异常 -
listIterator()返回的是“快照式”迭代器,它反映的是创建时列表的状态;后续其他线程或代码对列表的结构性修改(如clear())可能导致行为不可预期
掌握 ListIterator 的游标模型和方法约束,就能在需要双向导航或边遍历边编辑的场景中写出清晰、安全的代码。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











