iterator java 包_Java迭代器Iterator

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

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

1 packagejava.util;2

3 public interface Iterator{4

5 /**

6 *如果迭代器中还有元素则返回true7 */

8 booleanhasNext();9

10 /**

11 *返回迭代器中的下一个元素12 */

13 E next();14

15 /**

16 *通过迭代器删除处于集合中最底层的元素17 */

18 voidremove();19 }

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

c39252f01626af5e7b38c51262cdf0f6.png

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

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

1 public Iteratoriterator() {2 return newItr();3 }

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

1 private class Itr implements Iterator{2 int cursor; //返回下一个元素的索引

3 int lastRet = -1; //返回最后一个元素的索引;如果没有则返回-1

4 int expectedModCount =modCount;5

6 public booleanhasNext() {7 return cursor !=size;8 }9

10 @SuppressWarnings("unchecked")11 publicE next() {12 checkForComodification();13 int i =cursor;14 if (i >=size)15 throw newNoSuchElementException();16 Object[] elementData = ArrayList.this.elementData;17 if (i >=elementData.length)18 throw newConcurrentModificationException();19 cursor = i + 1;20 return (E) elementData[lastRet =i];21 }22

23 public voidremove() {24 if (lastRet < 0)25 throw newIllegalStateException();26 checkForComodification();27

28 try{29 ArrayList.this.remove(lastRet);30 cursor =lastRet;31 lastRet = -1;32 expectedModCount =modCount;33 } catch(IndexOutOfBoundsException ex) {34 throw newConcurrentModificationException();35 }36 }37

38 final voidcheckForComodification() {39 if (modCount !=expectedModCount)40 throw newConcurrentModificationException();41 }42 }

原来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的实现较为简单:

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

next的实现:

publicE next() {

checkForComodification();  //检查是否并发修改int i =cursor;if (i >=size)throw newNoSuchElementException();  //索引大于ArrayList大小抛出异常

Object[] elementData= ArrayList.this.elementData;  //后面实际是在取ArrayList中的数据if (i >=elementData.length)throw newConcurrentModificationException();

cursor= i + 1;return (E) elementData[lastRet =i];

}

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

final voidcheckForComodification() {if (modCount !=expectedModCount)throw newConcurrentModificationException();

}

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

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

public voidremove() {if (lastRet < 0)  //这个地方格外注意,不能在未调用next时直接调用remove方法,必须在remove调用前调用next方法,将通过cursor索引值将其值赋给lastRetthrow newIllegalStateException();

checkForComodification();try{

ArrayList.this.remove(lastRet);

cursor=lastRet;

lastRet= -1;

expectedModCount=modCount;

}catch(IndexOutOfBoundsException ex) {throw newConcurrentModificationException();

}

}

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

1 packageday_29_iterator;2

3 importjava.util.ArrayList;4 importjava.util.Iterator;5 importjava.util.List;6

7 /**

8 *@authorturbo9 *10 * 2016年9月29日11 */

12 public classMain {13

14 /**

15 *@paramargs16 */

17 public static voidmain(String[] args) {18 List list = newArrayList();19 list.add(1);20 list.add(2);21 Iterator iterator =list.iterator();22 while(iterator.hasNext()){23 System.out.println(iterator.next());24 }25 }26

27 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值