Iterabtor是从jdk1.2就存在的接口,称为外部迭代器。支持对容器中的元素进行遍历和移除,还支持流式遍历
外部迭代器的特点是:可拔插。其迭代行为可以挂载到待比较对象的外部, 此外,外部迭代器往往用来支撑内部迭代器的实现。
注意区别于内部迭代器Iterable和枚举器Enumeration
外部迭代器的设计背后体现着迭代器设计模式的思想
(二)源码分析该接口就只有四种方法
// 是否存在未遍历元素
boolean hasNext();
// 返回下一个元素
E next();
// 移除一个元素
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 流式遍历。遍历每个元素,并对其执行相应的择取操作
default void forEachRemaining(Consumer action) {
Objects.requireNonNull(action);
while(hasNext()) {
action.accept(next());
}
}
Consumer为一个函数式接口,择取从这里实现。Lambda表达式参考【Java 8 in Action】Lambda表达式
我们看一下外部迭代器是如何实现自己的作用的。
我们切到AbstractList抽象类。很容易发现存在Itr类实现了外部迭代器的接口
// 获取类的迭代器
public Iterator iterator() {
return new Itr();
}
// 修改的次数--集合的增删改查;都能引起modCount数值加1的操作
protected transient int modCount = 0;
private class Itr implements Iterator {
// 下一个元素的索引
int cursor = 0;
// 当前元素的索引,该索引的元素被删除了,则置为-1.
int lastRet = -1;
// 预期修改的次数
int expectedModCount = modCount;
// 判断是否有下一个元素
public boolean hasNext() {
return cursor != size();
}
// 返回下一个元素
public E next() {
// 调用判断方法
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
// 这个方法体现的是Fail-Fast机制。
// expectedModCount预期修改的次数,modCount就是实际修改的次数;
// 在迭代器中,首先定义了一个expectedModCount=modCount默认值是0;这样通过上面的checkForComodification()方法就可以判断list集合在迭代过程中是否被其他线程修改过,这里的修改就是集合的增删改查;因为这些操作都能引起modCount数值加1的操作,这样就使得迭代失败了。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ArrayList继承了AbstractList抽象类。知晓源码之后,我们再使用迭代器的API,一切都是那么自然。
public static void main(String[] args) {
ArrayList name= new ArrayList();
name.add("zhangsan");
name.add("lisi");
name.add("wangwu");
name.add("zhaoliu");
Iterator it=name.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
还有,checkForComodification方法,体现的是Fail-Fast机制(面试会问)。也说明了为什么外部迭代器遍历的时候,如果对集合进行操作,会抛出ConcurrentModificationException异常了。