迭代器Iterator
学集合之前我们先来学习迭代器?那什么是迭代器。
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素
以ArrayList中内部类itr实现的迭代器为例。
源码:
public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor;//获取当前元素索引 if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData;//获取数组对象 if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1;//索引前进 return (E) elementData[lastRet = i];//将当前索引赋给上一个lastRet标记 }
public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification();//检查是不是预期的modCount和原本的modCount相等,防止在迭代的时候对元素进行操作 try { ArrayList.this.remove(lastRet);//调用集合的remove方法 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
@Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]);//调用子类实现的accept方法对当前元素进行操作 } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); }
测试forEachRemaining例子
import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.*; public class THS { public static void main(String[] args) { ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); Iterator<Integer> iterator = arrayList.iterator(); while (iterator.hasNext()){ int c = iterator.next(); System.out.println(c); } Iterator<Integer> iterator1 = arrayList.iterator(); if (iterator1.hasNext()){ System.out.println(iterator1.next()+"测试"); } while (iterator1.hasNext()){ iterator1.forEachRemaining(e -> System.out.println(e+"测试")); } } }
注意:在遍历集合的时候,有一个modCount表示集合的元素被修改的次数,每次增加或删除一个元素的时候,modCount都会加一,而expectedModCount用于记录在集合遍历之前的modCount,检查这两者是否相等就是为了检查集合在迭代遍历的过程中有没有被修改,如果被修改了,就会在运行时抛出ConcurrentModificationException这个RuntimeException,但是使用Iterator的remove方法是可以的(删除的是迭代器指向的当前元素),在集合的元素被remove之后,expectedModCount被重新赋值,是的modCount总是等于expectedModCount,所以不会抛出ConcurrentModificationException异常。
测试代码
public static void main(String[] args) { ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); Iterator<Integer> iterator = arrayList.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()+"测试"); iterator.remove(); } } 结果: 1测试 2测试 3测试
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next()+"测试");
arrayList.remove(0);//抛异常
}
}
结果:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at THS.main(THS.java:15)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~