【JDK1.8源码剖析】外部迭代器Iterator接口

Janna ·
更新时间:2024-09-20
· 513 次阅读

文章目录Iterator源码剖析(一)简介(二)源码分析 Iterator源码剖析 (一)简介

Iterabtor是从jdk1.2就存在的接口,称为外部迭代器。支持对容器中的元素进行遍历和移除,还支持流式遍历

外部迭代器的特点是:可拔插。其迭代行为可以挂载到待比较对象的外部, 此外,外部迭代器往往用来支撑内部迭代器的实现。

注意区别于内部迭代器Iterable和枚举器Enumeration

外部迭代器的设计背后体现着迭代器设计模式的思想

(二)源码分析

该接口就只有四种方法
在这里插入图片描述

// 是否存在未遍历元素 boolean hasNext(); // 返回下一个元素 E next(); // 移除一个元素 default void remove() { throw new UnsupportedOperationException("remove"); } // 流式遍历。遍历每个元素,并对其执行相应的择取操作 default void forEachRemaining(Consumer action) { Objects.requireNonNull(action); while(hasNext()) { action.accept(next()); } }

Consumer为一个函数式接口,择取从这里实现。Lambda表达式参考【Java 8 in Action】Lambda表达式

我们看一下外部迭代器是如何实现自己的作用的。

我们切到AbstractList抽象类。很容易发现存在Itr类实现了外部迭代器的接口

// 获取类的迭代器 public Iterator iterator() { return new Itr(); } // 修改的次数--集合的增删改查;都能引起modCount数值加1的操作 protected transient int modCount = 0; private class Itr implements Iterator { // 下一个元素的索引 int cursor = 0; // 当前元素的索引,该索引的元素被删除了,则置为-1. int lastRet = -1; // 预期修改的次数 int expectedModCount = modCount; // 判断是否有下一个元素 public boolean hasNext() { return cursor != size(); } // 返回下一个元素 public E next() { // 调用判断方法 checkForComodification(); try { int i = cursor; E next = get(i); lastRet = i; cursor = i + 1; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } // 这个方法体现的是Fail-Fast机制。 // expectedModCount预期修改的次数,modCount就是实际修改的次数; // 在迭代器中,首先定义了一个expectedModCount=modCount默认值是0;这样通过上面的checkForComodification()方法就可以判断list集合在迭代过程中是否被其他线程修改过,这里的修改就是集合的增删改查;因为这些操作都能引起modCount数值加1的操作,这样就使得迭代失败了。 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }

ArrayList继承了AbstractList抽象类。知晓源码之后,我们再使用迭代器的API,一切都是那么自然。

public static void main(String[] args) { ArrayList name= new ArrayList(); name.add("zhangsan"); name.add("lisi"); name.add("wangwu"); name.add("zhaoliu"); Iterator it=name.iterator(); while(it.hasNext()){ System.out.println(it.next()); } }

在这里插入图片描述

还有,checkForComodification方法,体现的是Fail-Fast机制(面试会问)。也说明了为什么外部迭代器遍历的时候,如果对集合进行操作,会抛出ConcurrentModificationException异常了。


作者:沉晓



迭代 jdk1.8 iterator jdk 源码

需要 登录 后方可回复, 如果你还没有账号请 注册新账号