ListIterator 不能直接在指定索引插入元素,需先将光标移至目标索引前(即调用 next() 共 index 次或使用 listIterator(index)),再调用 add();末尾插入须用 listIterator(list.size()) 避免异常。

Java 中 ListIterator 本身不提供“在指定索引位置插入元素”的直接方法,它只能在**当前迭代器光标位置**前插入元素。所以“在指定位置插入”,本质是先将迭代器移动到目标索引的**光标位置**(即该索引处元素的前面),再调用 add()。
理解 ListIterator 的光标位置
ListIterator 的光标始终位于两个元素之间,或列表首尾。它的索引概念和 List 的索引不同:
- 调用
next()返回的是光标**后一个**元素,然后光标前移; - 调用
previous()返回的是光标**前一个**元素,然后光标后移; -
nextIndex()返回调用next()将获取的元素的索引(即光标当前位置对应“下一个元素”的下标); -
previousIndex()返回调用previous()将获取的元素的索引(即光标当前位置对应“前一个元素”的下标)。
例如,对列表 [A, B, C],初始光标在索引 0 前(即 nextIndex() == 0)。此时 add("X") 会把 X 插入到索引 0 位置,列表变为 [X, A, B, C]。
在指定索引位置插入元素的正确步骤
假设你想在 List 的索引 index 处插入元素 element(即插入后,element 占据该索引位置,原索引 index 及之后的元素全部后移):
立即学习“Java免费学习笔记(深入)”;
- 获取列表的
ListIterator,起始光标位置为0(即列表开头); - 调用
next()共index次,使光标移动到索引index处元素的前面(此时nextIndex() == index); - 调用
add(element)—— 元素将被插入到当前光标位置,也就是原列表的index索引处。
⚠️ 注意:如果 index == list.size()(即插到末尾),需用 list.listIterator(index) 直接定位,否则反复调用 next() 会抛出 NoSuchElementException。
完整示例代码
// 示例:在 ArrayList 的索引 2 处插入 "NEW"
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
ListIterator<String> lit = list.listIterator(); // 光标在索引 0 前
// 移动光标到索引 2 的前面(即 C 的前面)
for (int i = 0; i < 2; i++) {
lit.next(); // 调用 2 次:经过 A、B,光标停在 B 和 C 之间
}
lit.add("NEW"); // 插入到索引 2 位置
System.out.println(list); // [A, B, NEW, C, D]
更健壮的写法(支持任意合法索引,包括末尾):
public static <T> void insertAt(List<T> list, int index, T element) {
if (index < 0 || index > list.size()) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size());
}
ListIterator<T> lit = list.listIterator(index); // 直接定位光标到 index 位置(即索引 index 元素之前)
lit.add(element);
}
为什么不直接用 List.add(int, E)?
List.add(int index, E element) 更直观、高效且不易出错,是插入的标准方式。使用 ListIterator 插入通常只在以下场景有意义:
- 你已经在遍历列表,且需要在遍历过程中动态插入(避免
ConcurrentModificationException); - 你需要结合
next()/previous()判断上下文后再决定是否插入; - 你在实现自定义迭代逻辑(如双向扫描+条件插入)。
单纯为了“在某索引插入”,优先用 list.add(index, element)。


















