教程中心 / Java教程 / 迭代器

迭代器

8分钟 集合框架

什么是迭代器?

迭代器(Iterator)是一种设计模式,它提供了一种统一的方法来顺序访问集合中的元素,而不需要了解集合的内部结构。Java中的迭代器接口让我们可以遍历任何Collection类型的集合

生活比喻

迭代器就像博物馆的语音导览器。无论你参观的是绘画馆、雕塑馆还是文物馆,导览器都提供相同的操作:当前展品是什么?(hasNext())下一件展品是什么?(next())讲解完毕(remove())。游客不需要知道博物馆是如何布置展厅的。

迭代器遍历集合的流程:

    ┌─────────────────────────────────────────────┐
    │                                             │
    │   hasNext() ──→ true ──→ next() ──→ 处理元素 │
    │       ↑                        ↓            │
    │       └──── false (遍历结束) ←──┘            │
    │                                             │
    │   remove() 可在 next() 之后调用删除元素     │
    └─────────────────────────────────────────────┘

Iterator接口的方法

Iterator接口只有三个核心方法,简单却功能强大:

方法返回类型说明
hasNext()boolean判断是否还有下一个元素
next()E返回下一个元素,并将迭代器位置前移
remove()void删除上次调用next()返回的元素

Iterator基本用法

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorBasicDemo {
    public static void main(String[] args) {
        List fruits = new ArrayList<>();
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橙子");
        fruits.add("芒果");

        // 获取迭代器
        Iterator iterator = fruits.iterator();

        // 遍历
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            System.out.println("水果: " + fruit);
        }

        System.out.println("遍历完成!");
    }
}

为什么要用迭代器?

优势1:统一遍历方式

无论是List、Set还是Queue,都可以使用Iterator进行遍历。这种统一性让你可以在不知道集合具体类型的情况下遍历它。

// 这个方法可以遍历任何Collection集合
public void printAll(Collection collection) {
    Iterator it = collection.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}

// 使用
printAll(new ArrayList<>());
printAll(new HashSet<>());
printAll(new LinkedList<>());

优势2:安全删除元素

在遍历集合时,如果你直接使用for循环或foreach循环删除元素,可能会抛出ConcurrentModificationException异常。迭代器的remove()方法是专门设计来在遍历过程中安全删除元素的。

错误做法 vs 正确做法:

❌ 错误:foreach中删除
for (String s : list) {
    if (s.equals("要删除的")) {
        list.remove(s);  // ConcurrentModificationException!
    }
}

✓ 正确:使用迭代器删除
Iterator it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("要删除的")) {
        it.remove();  // 安全删除
    }
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SafeRemoveDemo {
    public static void main(String[] args) {
        List numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        numbers.add(6);

        System.out.println("删除前: " + numbers);

        // 使用迭代器安全删除所有偶数
        Iterator it = numbers.iterator();
        while (it.hasNext()) {
            Integer num = it.next();
            if (num % 2 == 0) {
                it.remove();  // 安全删除
                System.out.println("删除了: " + num);
            }
        }

        System.out.println("删除后: " + numbers);  // [1, 3, 5]
    }
}

ListIterator双向迭代器

ListIterator是List接口特有的迭代器,继承自Iterator。它支持双向遍历,还可以在遍历过程中修改列表。

方法说明
hasNext()判断是否有下一个元素(正向)
next()返回下一个元素(正向)
hasPrevious()判断是否有上一个元素(反向)
previous()返回上一个元素(反向)
nextIndex()返回下一个元素的索引
previousIndex()返回上一个元素的索引
add(E e)在当前位置添加元素
set(E e)替换上次返回的元素
remove()删除上次返回的元素
import java.util.ArrayList;
import java.util.ListIterator;

public class ListIteratorDemo {
    public static void main(String[] args) {
        ArrayList cities = new ArrayList<>();
        cities.add("北京");
        cities.add("上海");
        cities.add("广州");
        cities.add("深圳");

        ListIterator it = cities.listIterator();

        System.out.println("===== 正向遍历 =====");
        while (it.hasNext()) {
            int index = it.nextIndex();
            String city = it.next();
            System.out.println(index + ": " + city);
        }

        System.out.println("\n===== 反向遍历 =====");
        while (it.hasPrevious()) {
            int index = it.previousIndex();
            String city = it.previous();
            System.out.println(index + ": " + city);
        }

        System.out.println("\n===== 添加和修改 =====");
        // 把迭代器移回开始位置
        while (it.hasNext()) {
            it.next();
        }
        // 现在可以反向操作
        while (it.hasPrevious()) {
            String city = it.previous();
            if (city.equals("上海")) {
                it.set("上海市");  // 修改
                it.add("杭州");   // 添加
            }
        }

        System.out.println("修改后: " + cities);
    }
}

Iterator的高级用法

1. 遍历Map

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapIteratorDemo {
    public static void main(String[] args) {
        Map scores = new HashMap<>();
        scores.put("张三", 95);
        scores.put("李四", 87);
        scores.put("王五", 92);

        // 方法1:遍历entrySet
        System.out.println("方法1: 遍历entrySet");
        Iterator> entryIt = scores.entrySet().iterator();
        while (entryIt.hasNext()) {
            Map.Entry entry = entryIt.next();
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }

        // 方法2:遍历keySet
        System.out.println("\n方法2: 遍历keySet");
        Iterator keyIt = scores.keySet().iterator();
        while (keyIt.hasNext()) {
            String key = keyIt.next();
            System.out.println(key + " = " + scores.get(key));
        }

        // 方法3:使用Lambda(Java 8+)
        System.out.println("\n方法3: forEach + Lambda");
        scores.forEach((k, v) -> System.out.println(k + " = " + v));
    }
}

2. 条件删除多个元素

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class BatchRemoveDemo {
    public static void main(String[] args) {
        List words = new ArrayList<>();
        words.add("apple");
        words.add("banana");
        words.add("apricot");
        words.add("blueberry");
        words.add("cherry");

        // 删除所有以"a"开头的单词
        Iterator it = words.iterator();
        while (it.hasNext()) {
            if (it.next().startsWith("a")) {
                it.remove();
            }
        }

        System.out.println("删除后: " + words);
    }
}

3. 并行迭代(小心使用)

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorCaution {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");

        // 注意:一个迭代器不能用于两个独立的遍历
        Iterator it = list.iterator();
        it.next();  // 读取第一个

        // 如果再创建一个新的迭代器进行遍历
        Iterator it2 = list.iterator();  // 新迭代器从头开始

        // 两个迭代器独立使用是可以的
        System.out.println("迭代器1: " + it.next());  // B
        System.out.println("迭代器2: " + it2.next()); // A
    }
}

常见错误和注意事项

错误1:在调用next()之前先调用remove()

迭代器的remove()方法删除的是上次next()返回的元素。如果在还没调用next()之前就调用remove(),会抛出IllegalStateException。

Iterator it = list.iterator();
it.remove();  // ❌ IllegalStateException! 还没调用next()

错误2:连续调用两次remove()

每次remove()之后,上次返回的元素已经被删除了。如果不再次调用next()就调用remove(),会抛出IllegalStateException。

it.next();
it.remove();
it.remove();  // ❌ IllegalStateException! 需要先再调用next()

错误3:在迭代过程中修改集合(除迭代器的remove外)

在迭代集合时,如果通过其他方式(如list.remove())修改集合,会导致ConcurrentModificationException。

提示:Java 8+的forEach

对于简单的遍历,Java 8引入的forEach方法和Stream API提供了更简洁的写法。但迭代器仍然是修改集合的首选方式。

迭代器vs增强for循环

特性Iterator增强for循环
代码简洁性较繁琐简洁
安全删除支持不支持(会抛异常)
双向遍历ListIterator支持不支持
知道当前位置可以不知道
适用场景需要删除元素时仅遍历时

小结

  • Iterator提供了一种统一、安全的方式遍历任何Collection集合
  • 三个核心方法:hasNext()、next()、remove()
  • 使用迭代器的remove()可以在遍历时安全删除元素
  • ListIterator支持双向遍历和修改元素
  • 不要在迭代过程中通过其他方式修改集合
  • 增强for循环适合仅需要遍历的场景,需要删除时用迭代器
☕ Java 在线代码编辑器
📝 运行结果