JDK8源码之Iterator顺序遍历迭代器
来源:互联网 发布:什么是java设计模式 编辑:程序博客网 时间:2024/05/30 02:22
Iterator是什么?
public interface Iterator<E> {...}
iterator被称之为顺序遍历迭代器,jdk中默认对集合框架中数据结构做了实现。iterator在实际应用中有一个比较好的点就是,可以一边遍历一遍删除元素(不过需要自实现,好在jdk都帮你做了,哈哈),后面拿ArrayList.iterator()来说明怎么做到这点的。
Iterator结构
//是否能遍历到下一个元素。是返回true,否则返回false boolean hasNext(); //指向下一个元素 E next(); //删除当前元素,需要实现者重写,默认会抛错 default void remove() { throw new UnsupportedOperationException("remove"); } //顺序遍历元素,对每个元素执行指定事件,一直到遍历完所有元素 default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); }
ArrayList.iterator()解析
public Iterator<E> iterator() { //返回一个顺序遍历迭代器 return new Itr(); } private class Itr implements Iterator<E> { //指向下次将遍历到的位置 int cursor; //当前遍历到的位置,当为-1时,表示未指向元素 int lastRet = -1; //结构变更次数 int expectedModCount = modCount; //是否返拥有下个元素 public boolean hasNext() { return cursor != size; } //遍历到下个元素 @SuppressWarnings("unchecked") public E next() { //ArrayList是否发生结构变更操作 checkForComodification(); //得到当前遍历的位置 int i = cursor; //是否超出size大小 if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; //并发修改异常,elementData的结构发生变更 //(疑惑:这一段代码的意义,可以和forEachRemaining对比一下) if (i >= elementData.length) throw new ConcurrentModificationException(); //指向下次遍历到的位置 cursor = i + 1; //返回当前位置的值 return (E) elementData[lastRet = i]; } public void remove() { //如果当前遍历器未指向任何元素时,则报错 //未执行next()时和执行remove方法时 lastRet=-1 if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { //调用arrayList.remove方法来删除元素 ArrayList.this.remove(lastRet); //指针指向当前删除位置 cursor = lastRet; //lastRet置为-1,表示当前遍历器未指向任何元素 lastRet = -1; //这里是iteraotr可以遍历到元素后可以删除元素的关键 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { //consumer不能为空校验 Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; //遍历器还有元素未遍历完 if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; //并发修改异常,elementData的结构发生变更(这一段代码的意义,可以思考下) if (i >= elementData.length) { throw new ConcurrentModificationException(); } //遍历元素执行指定动作 while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
看到这一段代码的时候,我对forEachRemaining方法里面检查ConcurrentModificationException并发操作异常的情况有疑惑,在校验元素的size后,再将执行 Object[] elementData = ArrayList.this.elementData;再对elementData进行遍历操作同时并会对expectedModCount进行判断,因此遍历之前检查(i >= elementData.length) 感觉并没有什么用。
另外,ArrayList自身就不是线程安全的,modCount也只是用来保证快速失败,因此不要在多线程的环境下使用iterator进行并行遍历操作。如果需要并行遍历可以使用Spliterator进行并行遍历。
ArrayList.iterator本质上还是操作原list对象,只是通过一个单向指向list的索引而对原对象进行引用,因此iterator在工作的时候,我们如果对远list对象进行了结构上的变更,此时会通过expectedModCount比较modCount是否相等来实现fail-fast。而ArrayList.iterator.remove方法没有问题,是因为操作过后会同步更新expectedModCount的值。
0 0
- JDK8源码之Iterator顺序遍历迭代器
- JDK8源码之Spliterator并行遍历迭代器
- JDK8 源码之ArrayList
- jdk8之ConcurrentHashMap源码解析
- jdk8源码之Queue-ArrayQueue
- Jdk8源码阅读之InputStream
- jdk8源码阅读之Serializable
- JDK源码阅读之Iterator迭代器接口
- STL源码剖析之迭代器Iterator
- Iterator迭代器 遍历Map
- 设计模式之Iterator和容器与迭代器遍历
- JDK8 源码之HashMap(1)
- JDK8 源码之HashMap(2)
- jdk8 源码之HashSet 和 LinkedHashMap
- JDK8源码阅读之File(一)
- JDK8源码阅读之File(二)
- STL源码剖析之Iterator
- php中的iterator迭代器(遍历)
- java中静态代码块的用法static用法详解
- Android系统下的蓝牙协议
- Spring Cloud系列四 之 配置信息Server
- C语言实现面向对象思想
- 组合数的两种计算方法(递推,对数)
- JDK8源码之Iterator顺序遍历迭代器
- 学习Linux的第一天
- android判断service或者process是否运行
- Android ContentValues的用法
- Spring Cloud系列五 之 服务网关
- 视频播放器(SurfaceView+MediaPlayer+SeekBar,VideoView+MediaController)
- 安卓漫漫路之AndroidManifest权限大全.
- 正则表达式2(常用)
- Opencv2系列学习笔记4(灰度直方图)