Iterator 使用详细说明

1. 什么是 Iterator?

Iterator 是 Java 集合框架中用于遍历集合元素的接口,位于 java.util 包下。
它提供了一种统一的方式来遍历 Collection(如 List、Set)中的元素,而无需关心底层实现。


2. Iterator 的常用方法

方法说明
boolean hasNext()是否还有下一个元素
E next()返回下一个元素,并将游标向后移动
void remove()移除当前迭代器返回的元素(可选操作)
default void forEachRemaining(Consumer)对剩余元素执行指定操作(Java 8+)

3. 使用示例

3.1 遍历 List

List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

3.2 遍历 Set

 

Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = set.iterator();

while (it.hasNext()) {
    Integer num = it.next();
    System.out.println(num);
}

3.3 使用 remove() 删除元素

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (item.equals("b")) {
        iterator.remove(); // 删除当前元素
    }
}
System.out.println(list); // 输出: [a, c]

注意:
不能在遍历时直接用 list.remove(item),否则会抛 ConcurrentModificationException


4. Iterator 的底层原理

  • 每个集合类(如 ArrayList、HashSet)都有自己的内部迭代器实现。
  • 迭代器内部维护一个游标(指针),每次调用 next() 时,游标向后移动。
  • hasNext() 判断游标是否到达末尾。

5. Iterator 的常见异常

5.1 NoSuchElementException

当没有元素可遍历时,继续调用 next() 会抛出此异常。

示例:

List<String> list = new ArrayList<>();
Iterator<String> it = list.iterator();
it.next(); // 抛 NoSuchElementException

5.2 ConcurrentModificationException

在使用迭代器遍历集合的过程中,如果直接用集合的方法(如 remove()add())修改集合,会抛出此异常。

示例:

List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    list.remove(s); // 抛 ConcurrentModificationException
}

正确做法: 用 iterator.remove()


6. for-each 与 Iterator 的关系

Java 的 for-each(增强型 for 循环)底层其实也是用 Iterator 实现的。例如:

for (String s : list) {
    System.out.println(s);
}

等价于:

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    System.out.println(s);
}

7. forEachRemaining 的用法(Java 8+)

Iterator<String> it = list.iterator();
it.forEachRemaining(item -> System.out.println(item));

对剩余的元素执行 lambda 表达式。


8. 适用场景

  • 需要在遍历过程中安全地删除元素时。
  • 需要对不同类型的集合统一遍历时。
  • 需要手动控制遍历流程时。

9. 小结与注意事项

  • 遍历时用 hasNext() 判断是否有元素,next() 取元素。
  • 删除元素应使用 iterator.remove()
  • 不要在遍历时直接用集合的添加/删除方法。
  • for-each 循环底层也是用 Iterator 实现的。

10. ListIterator 与 Iterator 的区别

ListIterator 是 Iterator 的子接口,只能用于 List(如 ArrayList、LinkedList),功能更强大:

特性IteratorListIterator
支持遍历方向只能向前可以双向(前/后)遍历
支持元素修改只能删除可增、删、改元素
可获取当前索引有(nextIndex/previousIndex)
适用集合类型所有 Collection仅 List

示例:

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
ListIterator<String> it = list.listIterator();

while (it.hasNext()) {
    String s = it.next();
    if (s.equals("b")) {
        it.set("B"); // 修改元素
        it.add("bb"); // 插入元素
    }
}
System.out.println(list); // 输出: [a, B, bb, c]

11. 线程安全问题

1. 普通集合的 Iterator 不是线程安全的

在多线程环境下,若一个线程遍历,另一个线程修改集合,可能会抛 ConcurrentModificationException

2. 解决办法

  • 使用 Collections.synchronizedList() 包装集合
  • 或使用并发集合(如 CopyOnWriteArrayList

示例:

List<String> list = Collections.synchronizedList(new ArrayList<>());
synchronized (list) {
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}

12. 如何自定义 Iterator

如果你自己写了一个集合类,也可以实现 Iterable 接口,并提供自己的 Iterator:

public class MyCollection implements Iterable<String> {
    private String[] data = {"x", "y", "z"};

    @Override
    public Iterator<String> iterator() {
        return new Iterator<String>() {
            private int index = 0;
            public boolean hasNext() {
                return index < data.length;
            }
            public String next() {
                if (!hasNext()) throw new NoSuchElementException();
                return data[index++];
            }
        };
    }
}

这样你的集合就可以用 for-each 或 Iterator 方式遍历了。


13. 实际开发建议

  • 删除元素时用 iterator.remove(),不要直接用集合的 remove。
  • 遍历前判断集合是否为空,避免空指针异常。
  • 在多线程环境下,优先考虑并发集合或加锁。
  • 不要在遍历时修改集合结构(增删元素),除非用 iterator.remove()/listIterator.add()。
  • 使用 for-each 循环时不能删除元素,否则会报错。

14. 常见面试题

  1. Iterator 和 ListIterator 有什么区别?
  2. 如何安全地遍历并删除集合中的元素?
  3. 为什么直接用集合的 remove 方法会抛 ConcurrentModificationException?
  4. Iterator 的底层原理是什么?
  5. 如何自定义一个集合的 Iterator?

15. 代码示例:安全删除元素

List<Integer> nums = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Iterator<Integer> it = nums.iterator();
while (it.hasNext()) {
    Integer n = it.next();
    if (n % 2 == 0) {
        it.remove(); // 删除偶数
    }
}
System.out.println(nums); // 输出: [1, 3, 5]

16. 其他高级用法

使用 forEachRemaining (Java 8+)

Iterator<String> it = list.iterator();
it.forEachRemaining(s -> {
    // 对剩余元素做操作
    System.out.println(s);
});

迭代 Map

遍历 Map 时,通常用 entrySet() 获取键值对:

Map<String, Integer> map = new HashMap<>();
map.put("A", 1); map.put("B", 2);
Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry<String, Integer> entry = it.next();
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

17. 总结

  • Iterator 是遍历集合的标准工具,支持安全删除。
  • ListIterator 适合 List,支持双向遍历和元素修改。
  • 多线程环境要用并发集合或加锁。
  • 删除元素用 iterator.remove(),不要用集合的 remove。
  • for-each 循环底层也是 Iterator。
  • 熟悉这些用法,能避免常见异常和编程陷阱。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猩火燎猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值