Java Iterator(迭代器)

张开发
2026/4/8 3:06:05 15 分钟阅读

分享文章

Java Iterator(迭代器)
Java Iterator迭代器学习笔记详细版一、Iterator 概述Iterator迭代器是 Java 集合框架中用于遍历集合元素的标准接口。它提供了一种统一的方式来访问集合中的元素而无需暴露集合底层的内部结构如数组、链表等。核心特点统一接口无论底层是ArrayList、HashSet还是LinkedList都可以通过Iterator进行遍历。单向遍历只能向前遍历next()不能向后移动除非使用ListIterator。安全删除提供了remove()方法可以在遍历过程中安全地删除元素避免ConcurrentModificationException。惰性加载迭代器通常不会一次性加载所有数据而是按需获取。二、核心接口与方法java.util.IteratorE接口主要包含三个核心方法方法说明返回值boolean hasNext()判断集合中是否还有下一个元素true有false无E next()返回下一个元素并将游标向后移动一位元素对象void remove()删除next()方法返回的最后一个元素无⚠️重要规则remove()方法必须在next()方法调用之后调用。每次next()调用后只能调用一次remove()。如果在调用next()之前调用remove()会抛出IllegalStateException。三、基本使用示例1. 标准遍历流程importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassIteratorDemo{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(Java);list.add(Python);list.add(C);list.add(Go);// 1. 获取迭代器IteratorStringiteratorlist.iterator();// 2. 遍历while(iterator.hasNext()){Stringlangiterator.next();System.out.println(lang);}}}2. 遍历中安全删除元素这是Iterator最核心的优势。如果在遍历过程中直接调用集合的remove()方法会抛出异常。importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassSafeRemoveDemo{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(Java);list.add(Python);list.add(C);list.add(Go);IteratorStringiteratorlist.iterator();while(iterator.hasNext()){Stringlangiterator.next();// 删除包含 C 的元素if(lang.contains(C)){iterator.remove();// ✅ 安全删除// list.remove(lang); // ❌ 错误会抛出 ConcurrentModificationException}}System.out.println(list);// 输出[Java, Python, Go]}}四、Iterator 与增强 for 循环的关系增强 for 循环for-each本质上是Iterator的语法糖。// 写法 A增强 for 循环for(Stringlang:list){System.out.println(lang);}// 写法 B底层等价代码 (Iterator)IteratorStringiteratorlist.iterator();while(iterator.hasNext()){Stringlangiterator.next();System.out.println(lang);}区别对比特性增强 for 循环Iterator 接口语法简洁性高代码更简洁低代码稍繁琐删除元素❌不支持(会抛异常)✅支持(remove())获取索引❌ 不支持❌ 不支持 (需ListIterator)适用场景仅遍历不修改集合遍历且需要删除元素结论如果只需要遍历优先使用增强 for 循环如果需要在遍历中删除元素必须使用Iterator。五、底层原理快速失败机制 (Fail-Fast)1. 什么是 Fail-FastJava 集合的迭代器如ArrayList、HashMap默认是Fail-Fast快速失败机制。如果在遍历过程中除了迭代器自身的remove()方法外其他任何地方修改了集合的结构添加、删除、修改元素迭代器会立即抛出ConcurrentModificationException。2. 实现原理集合类内部维护一个modCount变量记录集合被修改的次数。迭代器内部维护一个expectedModCount变量初始化为创建迭代器时的modCount。每次调用next()或remove()时都会检查modCount expectedModCount。如果不相等说明集合被外部修改了抛出异常。3. 异常示例ListStringlistnewArrayList();list.add(A);list.add(B);IteratorStringitlist.iterator();while(it.hasNext()){Stringsit.next();if(A.equals(s)){list.remove(s);// ❌ 直接调用集合的 remove导致 modCount 变化}}// 抛出java.util.ConcurrentModificationException4. 如何避免方法一使用Iterator的remove()方法推荐。方法二使用 Java 8 的removeIf方法底层也是迭代器。list.removeIf(s-s.contains(A));方法三使用Fail-Safe迭代器如CopyOnWriteArrayList或ConcurrentHashMap的迭代器它们不抛异常但可能读取到旧数据。六、ListIteratorList 专用的迭代器ListIterator继承自Iterator是List集合特有的迭代器功能更强大。核心增强功能双向遍历支持向前 (previous()) 和向后 (next()) 移动。获取索引支持nextIndex()和previousIndex()。修改元素支持set(E e)方法替换当前元素。添加元素支持add(E e)方法在当前位置插入元素。使用示例importjava.util.ArrayList;importjava.util.ListIterator;publicclassListIteratorDemo{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(A);list.add(B);list.add(C);// 获取 ListIteratorListIteratorStringlitlist.listIterator();// 1. 向后遍历System.out.println(向后遍历:);while(lit.hasNext()){System.out.println(lit.next());}// 2. 向前遍历 (从末尾开始)System.out.println(向前遍历:);while(lit.hasPrevious()){System.out.println(lit.previous());}// 3. 修改元素 (将 B 改为 Java)litlist.listIterator();// 重置while(lit.hasNext()){Stringslit.next();if(B.equals(s)){lit.set(Java);// 替换当前元素lit.add(Python);// 在 Java 后插入}}System.out.println(list);// [A, Java, Python, C]}}七、Iterator 与 Iterable 的关系Iterable 接口位于java.lang包。只有一个方法IteratorE iterator()。实现了Iterable接口的类才能使用增强 for 循环。所有Collection接口List, Set, Queue都继承了Iterable。关系图Iterable (接口) ^ | (实现) Collection (接口) ^ | (实现) List, Set, Queue ^ | (提供方法) iterator() - 返回 Iterator 对象八、常见面试题Q1: 为什么在遍历集合时不能直接调用集合的 remove 方法答因为集合的迭代器默认是Fail-Fast机制。直接调用集合的remove会修改modCount而迭代器内部的expectedModCount未更新下次调用next()时检测到不一致抛出ConcurrentModificationException。应使用迭代器的remove()方法它会自动同步expectedModCount。Q2: Iterator 和 ListIterator 的区别答适用范围Iterator适用于所有 CollectionListIterator仅适用于List。方向Iterator单向ListIterator双向。功能ListIterator支持add、set、previous、索引获取Iterator仅支持remove。Q3: 什么是 Fail-Fast 和 Fail-Safe答Fail-Fast遍历中检测到集合结构被修改非迭代器自身操作立即抛异常。如ArrayList、HashMap。Fail-Safe遍历的是集合的副本或快照不受原集合修改影响不抛异常但可能读取不到最新数据。如CopyOnWriteArrayList、ConcurrentHashMap。Q4: 如何遍历 Map 的 Entry答MapString,IntegermapnewHashMap();// 方式 1EntrySet (推荐性能最好)for(Map.EntryString,Integerentry:map.entrySet()){System.out.println(entry.getKey() entry.getValue());}// 方式 2KeySetfor(Stringkey:map.keySet()){System.out.println(key map.get(key));}九、最佳实践优先使用增强 for 循环代码简洁除非需要删除元素。需要删除时使用 Iterator这是唯一安全的遍历删除方式在 Fail-Fast 集合中。多线程环境如果并发修改使用CopyOnWriteArrayList或ConcurrentHashMapFail-Safe。或者使用Collections.synchronizedList配合手动同步代码块。避免在迭代器中修改集合状态除了remove()和ListIterator的add/set外不要调用集合的其他修改方法。Java 8 推荐使用removeIf或 Stream API 进行过滤和删除代码更函数式。list.removeIf(s-s.length()5);十、总结Iterator是 Java 集合框架的基石之一它✅ 屏蔽了底层数据结构的差异提供统一的遍历方式。✅ 提供了安全的删除机制remove()。✅ 通过 Fail-Fast 机制保证了数据的一致性在单线程下。✅ListIterator扩展了 List 的遍历能力双向、修改、插入。掌握Iterator的使用场景和原理是编写健壮、高效 Java 代码的关键。

更多文章