java基础-ListIterator 接口

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. 性能考虑

  1. 对于 ArrayList: ListIterator 提供 O(1) 的访问时间

  2. 对于 LinkedList: 需要小心使用,频繁的 previous() 调用可能影响性能

  3. 内存占用: 每个 ListIterator 需要维护当前位置和修改计数

总结

ListIterator 是处理 List 集合最强大的工具之一,特别适合需要:

  • 双向遍历

  • 遍历时修改(添加、删除、替换)

  • 需要知道当前位置索引

  • 实现复杂列表算法

关键要点:

  1. 始终检查 hasNext()/hasPrevious() 避免异常

  2. 注意 add()remove()set() 的调用顺序限制

  3. 理解并发修改的约束

  4. 合理使用索引定位功能

相关推荐
程序员清风1 天前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5511 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊1 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing1 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠2 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840822 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide2 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家2 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺2 天前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户908324602732 天前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端