之前我们实现了迭代器模式,很多编程语言实际上已经内置了迭代器类,比如Java就为我们实现了迭代器Iterator。我们首先来看Iterator中的源码。

通过JDK源码我们发现Iterator是一个接口,包含三个方法:hasNext、next、remove。

 package java.util;

 public interface Iterator<E> {

     /**
*如果迭代器中还有元素则返回true
*/
boolean hasNext(); /**
*返回迭代器中的下一个元素
*/
E next(); /**
*通过迭代器删除处于集合中最底层的元素
*/
void remove();
}

Iterator是一个接口,那如何来创建一个实例呢?要记住,迭代器和集合类的关系非常紧密,我们可以通过集合类来创建一个Iterator实例,ArrayList、LinkedList、Vector都有对它的实现。我们来看ArrayList是如何创建一个Iterator迭代器实例的。在此之前我们先来看看集合和迭代器之间的继承关系。

由于集合的关系相对来说比较复杂,在此我们主要看注释部分,通过阅读源代码会发现ArrayList覆写了AbstractList抽象类中的iterator方法并声称效果更佳,而LinkedList则没有覆写,由此可判断ArrayList的iterator方法比LinkedList中的iterator方法更为高效。

我们直接看ArrayList里中实现的iterator方法。

 public Iterator<E> iterator() {
return new Itr();
}

从代码来看它返回类一个Itr的对象实例,顺着代码看看这个Itr类是什么。

 private class Itr implements Iterator<E> {
int cursor; // 返回下一个元素的索引
int lastRet = -1; // 返回最后一个元素的索引;如果没有则返回-1
int expectedModCount = modCount; 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];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

原来Itr它是一个私有的内部类,实现Iterator接口。

我们来一行一行读。在第3行中有一个modCount变量。跟踪这个变量,发现这个变量有点意思:

protected transient int modCount = 0;

发现有一个“transient”关键字,查阅资料发现这个关键字的意思是:表示一个域不是该对象序列化的一部分。意思是在对象被序列化时不包括这个变量,至于为什么要这么做呢,我们可以留下一个疑问。(JDk源码注释中是这么说的:The modCount value that the iterator believes that the backing List should have. If this expectation is violated, the iterator has detected concurrent modification.英语太次只能读懂最后一句:如果这个期望是可见性的,那么这个迭代器会检测到有一个并发的修改。猜测是和并发多线程相关。)

hasnext的实现较为简单:

 public boolean hasNext() {
return cursor != size;  //下一个元素的索引是否等于ArrayList的大小
}

next的实现:

public E next() {
checkForComodification();  //检查是否并发修改
int i = cursor;
if (i >= size)
throw new NoSuchElementException();  //索引大于ArrayList大小抛出异常
Object[] elementData = ArrayList.this.elementData;  //后面实际是在取ArrayList中的数据
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}

在next方法中我们看到有一个checkForCommodification方法:

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

看来这个modCount变量确实是和并发相关,如果expectedModCount和modCount这两个值不同,则抛出当前正在并发修改的异常。

最后我们来看remove方法的实现:

public void remove() {
if (lastRet < 0)  //这个地方格外注意,不能在未调用next时直接调用remove方法,必须在remove调用前调用next方法,将通过cursor索引值将其值赋给lastRet
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

在remove方法中我们要格外注意,在第一句是检测lastRet是否小于0,我们初始化了lastRet变量-1的值,这意味着,如果我们如果创建完Iterator实例后直接调用remove方法会抛出一个IllegalStateException异常,那怎么才能正确调用呢?那就是在调用remove方法前先调用next方法,此时lastReturn通过cursor索引被赋值,这个时候才能正确使用remove方法。同时它也会调用checkForCommodification方法做并发修改检测。其实我们可以看到JDK源码之所以写到好,是因为它每个方法都做了很多的检测,以确保在尽量多的场景下准确无误地运行。今天关于Java的迭代器就通过JDK源码简单介绍,通过对源码的阅读能够加深我们的理解,这还只是简单的阅读,并没有做很深的理解。最后,我们以为一个Iterator的例子结尾。

 package day_29_iterator;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; /**
* @author turbo
*
* 2016年9月29日
*/
public class Main { /**
* @param args
*/
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
} }

Java迭代器Iterator的更多相关文章

  1. 设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释

    迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(ite ...

  2. [转载]Java迭代器(iterator详解以及和for循环的区别)

    Java迭代器(iterator详解以及和for循环的区别) 觉得有用的话,欢迎一起讨论相互学习~[Follow] 转载自 https://blog.csdn.net/Jae_Wang/article ...

  3. Java 迭代器 Iterator

    迭代器模式 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式.这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示. 迭代器模式属于行 ...

  4. java 迭代器iterator

    对于如ArrayList<E>类的数据,常用iterator遍历. ArrayList<String> list = new ArrayList<String>() ...

  5. Java 迭代器综述

    一.摘要 迭代器模式是与集合共生共死的.一般来说.我们仅仅要实现一个容器,就须要同一时候提供这个容器的迭代器.使用迭代器的优点是:封装容器的内部实现细节,对于不同的集合,能够提供统一的遍历方式,简化c ...

  6. JAVA ,Map接口 ,迭代器Iterator

    1.    Map 接口概述 java.util.Map 接口描述了映射结构, Map 接口允许以键集.值集合或键 - 值映射关系集的形式查看某个映射的内容. Java 自带了各种 Map 类. 这些 ...

  7. Java之iterator迭代器和iterable接口

    java.lang.Iterable java.util.Iterator Iterator是迭代器类,而Iterable是接口. 好多类都实现了Iterable接口,这样对象就可以调用iterato ...

  8. Java 实现迭代器(Iterator)模式

    类图 /** * 自己定义集合接口, 相似java.util.Collection * 用于数据存储 * @author stone * */ public interface ICollection ...

  9. java基础知识5--集合类(Set,List,Map)和迭代器Iterator的使用

    写的非常棒的一篇总结: http://blog.csdn.net/speedme/article/details/22398395#t1 下面主要看各个集合如何使用迭代器Iterator获取元素: 1 ...

随机推荐

  1. Maven 自定义 archetype

    最近在公司经常要写一些 storm-job 工程的骨架(archetype)非常相似,为了能够将大家的工程结构固定下来以及节约建工程的成本,所以给组内自定义了maven-archetype,中途遇到了 ...

  2. CodeFirst的一些操作!!

    CodeFirst的一些操作!! 转载 2016-08-05 21:03:32 1 首先是codefirst怎么做,这个首先肯定要引入EntityFramework,然后在model中创建实体类,例如 ...

  3. 【转】一个工具类(可以控制多层嵌套的movieClip)

    好多人也应该遇到和我一样的问题,当设计师给了我们一个多层嵌套的movieClip时,我们在写代码时无法将movieClip完全停止掉,主要是基于好多movieClip有深层嵌套,主时间轴不在最上层导致 ...

  4. 1.Redis 的安装

    一.Redis 介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 作为Key-value型数据库,Red ...

  5. Java中利用BigInteger类进行大数开方

    在Java中有时会用到大数据,基本数据类型的存储范围已经不能满足要求了,如要对10的1000次方的这样一个数据规模的数进行开方运算,很明显不能直接用Math.sqrt()来进行计算,因为已经溢出了. ...

  6. 使用纯CSS方案,解决垂直居中

    CSS是HTML元素的剪刀手,它极度的丰富了web页面的修饰.在众多CSS常见的样式需求中,有一奇葩式的存在[垂直居中],因为不管是从逻辑实现方面还是从正常需求量来讲,这都没理由让这个需求在实践过程中 ...

  7. angular 过滤排序

    <table class="table"> <thead> <tr> <th ng-click="changeOrder('id ...

  8. vue学习笔记-one

    学习vue基础以来,看各种教程,练习,随手写写,有错误请大家指导, 目前vue已经升级到2.0的版本,学习也最好是2.0的版本开始. 先看vue的几个特点:1,简单,2,轻量,3,模块友好 4, 组件 ...

  9. React-Native 之 redux 与 react-redux

    前言 本文 有配套视频,可以酌情观看. 文中内容因各人理解不同,可能会有所偏差,欢迎朋友们联系我讨论. 文中所有内容仅供学习交流之用,不可用于商业用途,如因此引起的相关法律法规责任,与我无关,如文中内 ...

  10. websoket使用Protocol Buffers3.0传输

    Protocol Buffers是Google推出的一个数据交换格式,相对于xml它的体积更小,更快,因为它是二进制传输的.3.0相对于2.0变动比较大.这些变动可以去看官方说明. 在前端使用Prot ...