一、概述
Java集合框架的集合类因为内部结构不同,为了对容器内元素操作更为简单引入了迭代器模式。
迭代器模式就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节。
Collection 继承了 Iterable 接口,其中的 iterator() 方法能够产生一个 Iterator 对象,通过这个对象就可以迭代遍历 Collection 中的元素。
Iterator接口
Iterator为一个接口,它只提供了迭代的基本规则。
|
|
Iterable接口
Iterable接口包含一个能产生Iterator对象的方法,并且Iterable被foreach用来在序列中移动。因此如果创建了实现Iterable接口的类,都可以将它用于foreach中。
|
|
二、遍历
List遍历
1.使用for遍历
|
|
2.使用迭代器遍历
|
|
3.使用foreach遍历
|
|
注:Set除了不能使用for遍历2、3两种都可以
Map遍历
1.通过keySet遍历
|
|
2.通过entrySet使用迭代器
|
|
3.通过enrtySet遍历
|
|
4.通过values遍历value
|
|
Queue后面单独来看
三、Iterator遍历注意点
ConcurrentModificationException异常
在使用Iterator时候对所遍历的容器进行改变其大小的操作。例如对集合进行了add、remove操作就会出现ConcurrentModificationException异常。
示例代码:
|
|
源码分析
看ArrayList的iterator方法实现,源码如下:
|
|
1.首先看checkForComodification()
方法,会比较modCount和expectedModCount是否相等
modCount
是当前集合的版本号,每次修改集合都会加1expectedModCount
是当前迭代器的版本号,在迭代器实例化时初始化为modCount
2.ArrayList调用add()
或remove()
方法都只更新modCount
,expectedModCount
则没有更新,所以调用迭代器的next()
方法时会抛ConcurrentModificationException
异常
3.如果使用Iterator.remove()
方法则不会抛出异常,因为源码中调用了expectedModCount = modCount;
所以当调用next()
方法的时候就正常。
该机制主要目的是为了实现ArrayList中的快速失败机制(fail-fast),在Java集合中较大一部分集合是存在快速失败机制的。