博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中Iterator(迭代器)的用法及其背后机制的探究
阅读量:5952 次
发布时间:2019-06-19

本文共 3554 字,大约阅读时间需要 11 分钟。

在Java中遍历List时会用到Java提供的Iterator,Iterator十分好用,原因是:

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

  Java中的Iterator功能比较简单,并且只能单向移动:

  (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

  (2) 使用next()获得序列中的下一个元素。

  (3) 使用hasNext()检查序列中是否还有元素。

  (4) 使用remove()将迭代器新返回的元素删除。

只要看看下面这个例子就一清二楚了:

import java.util.*;public class Muster {	public static void main(String[] args) {		ArrayList list = new ArrayList();		list.add("a");		list.add("b");		list.add("c");		Iterator it = list.iterator();		while(it.hasNext()){			String str = (String) it.next();			System.out.println(str);		}	}}

运行结果:

a

b
c

可以看到,Iterator可以不用管底层数据具体是怎样存储的,都能够通过next()遍历整个List。

但是,具体是怎么实现的呢?背后机制究竟如何呢?

这里我们来看看Java里AbstractList实现Iterator的源代码

1.public abstract class AbstractList
extends AbstractCollection
implements List
{ // List接口实现了Collection
, Iterable
2. 3. protected AbstractList() { 4. } 5. 6. ... 7. 8. public Iterator
iterator() { 9. return new Itr(); // 这里返回一个迭代器10. } 11. 12. private class Itr implements Iterator
{ // 内部类Itr实现迭代器13. 14. int cursor = 0; 15. int lastRet = -1; 16. int expectedModCount = modCount; 17. 18. public boolean hasNext() { // 实现hasNext方法19. return cursor != size(); 20. } 21. 22. public E next() { // 实现next方法23. checkForComodification(); 24. try { 25. E next = get(cursor); 26. lastRet = cursor++; 27. return next; 28. } catch (IndexOutOfBoundsException e) { 29. checkForComodification(); 30. throw new NoSuchElementException(); 31. } 32. } 33. 34. public void remove() { // 实现remove方法35. if (lastRet == -1) 36. throw new IllegalStateException(); 37. checkForComodification(); 38. 39. try { 40. AbstractList.this.remove(lastRet); 41. if (lastRet < cursor) 42. cursor--; 43. lastRet = -1; 44. expectedModCount = modCount; 45. } catch (IndexOutOfBoundsException e) { 46. throw new ConcurrentModificationException(); 47. } 48. } 49. 50. final void checkForComodification() { 51. if (modCount != expectedModCount) 52. throw new ConcurrentModificationException(); 53. } 54. } 55.}

可以看到,实现next()是通过get(cursor),然后cursor++,通过这样实现遍历。

这部分代码不难看懂,唯一难懂的是remove操作里涉及到的expectedModCount = modCount;

在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程中集合的安全性。

从源代码里可以看到增删操作都会使modCount++,通过和expectedModCount的对比,迭代器可以快速的知道迭代过程中是否存在list.add()类似的操作,存在的话快速失败!
在第一个例子基础上添加一条语句:
import java.util.*;public class Muster {	public static void main(String[] args) {		ArrayList list = new ArrayList();		list.add("a");		list.add("b");		list.add("c");		Iterator it = list.iterator();		while(it.hasNext()){			String str = (String) it.next();			System.out.println(str);			list.add("s");        //添加一个add方法		}	}}

运行结果:

a

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
  at java.util.ArrayList$Itr.next(Unknown Source)
  at com.hasse.Muster.main(Muster.java:11)

这就会抛出一个下面的异常,迭代终止。
 
关于modCount,API解释如下:
The number of times this list has been structurally modified. Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.
也就是说,modCount记录修改此列表的次数:包括
改变列表的结构,改变列表的大小,打乱列表的顺序等使正在进行迭代产生错误的结果。
Tips:仅仅设置元素的值并不是结构的修改
我们知道的是ArrayList是线程不安全的,如果在使用迭代器的过程中有其他的线程修改了List就会抛出ConcurrentModificationException,这就是
Fail-Fast机制。

 

转载于:https://www.cnblogs.com/hasse/p/5024193.html

你可能感兴趣的文章
Eclipse安装adt插件后之后看不到andorid manger
查看>>
Kafka服务端脚本详解(1)一topics
查看>>
Zookeeper 集群安装配置,超详细,速度收藏!
查看>>
js中var self=this的解释
查看>>
js--字符串reverse
查看>>
面试题
查看>>
Facebook 接入之获取各个配置参数
查看>>
android ant Compile failed; see the compiler error
查看>>
项目经理笔记一
查看>>
[原]Jenkins(三)---Jenkins初始配置和插件配置
查看>>
Cache Plugin 实现过程
查看>>
TCP服务器端口转发: netsh
查看>>
nginx实现rtmp,flv,mp4流媒体服务器
查看>>
46.tornado绑定域名或者子域名泛域名的处理
查看>>
文本过滤--sed 1
查看>>
PHP CURL并发,多线程
查看>>
ES 概念及动态索引结构和索引更新机制
查看>>
iOS 开发百问(2)
查看>>
MySQL for Mac 安装和基本操作(包含后期的环境变量设置)
查看>>
Linux及windows下常见压缩程序的压缩能力对比
查看>>