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. 合理使用索引定位功能

相关推荐
AI进化营-智能译站21 小时前
ROS2 C++开发系列07-高效构建机器人决策逻辑,运算符与控制流实战
开发语言·c++·ai·机器人
winner888121 小时前
C++ 命名空间、虚函数、抽象类、protected 权限全套通俗易懂精讲(附与 Java 对比)
java·开发语言·c++
不会编程的懒洋洋21 小时前
C# P/Invoke 基础
开发语言·c++·笔记·安全·机器学习·c#·p/invoke
直奔標竿21 小时前
Java开发者AI转型第二十五课!Spring AI 个人知识库实战(四)——RAG来源追溯落地,拒绝AI幻觉
java·开发语言·人工智能·spring boot·后端·spring
时空系21 小时前
认识Rust——我的第一个程序 Rust中文编程
开发语言·后端·rust
yqcoder21 小时前
JavaScript 柯里化:把“大餐”拆成“小炒”的艺术
开发语言·javascript·ecmascript
每天吃饭的羊21 小时前
JSZip的使用
开发语言·javascript
qq_5895681021 小时前
java基础学习,案例练习,即时通讯
java·开发语言·学习
DevilSeagull21 小时前
Windows 批处理 (Batch) 编程: 从入门到入土. (一) 基础概念与环境配置
开发语言·windows·后端·batch·语言