今天看了迭代器的源码,发现并不难,接下来记录讲解
我们直到迭代器Iterator是一个接口,它的接口与本身并没有全部实现方法。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
最下面的方法我没看,以后有时间看了再更
既然没有实现next等常用方法,我们知道迭代器是服务与集合类Collection中,那么我们集合类Collection中找找看。
Iterator<E> iterator();
我们发现collection中只有一个迭代器类型的属性,既然找不到我们继续向下找
我们直接去ArrayList类里去找:
我们发现iterator方法继承自AbstractList抽象类
public Iterator<E> iterator() {
return new Itr();
}
那我们去找itr类。
private class Itr implements Iterator<E> {
//这个属性记录上一次遍历的结点的下一个结点的索引
int cursor = 0;
//这个属性记录上一次遍历的结点的索引。如果这个结点被删除则设这个属性为-1
int lastRet = -1;
/*这两个属性与快速失败有关,代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。
集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。*/
int expectedModCount = modCount;
//判断是否遍历到末尾
public boolean hasNext() {
//这里说下因为索引是从0开始的,所以应该到size()-1结束,但是cursor存的是下一个结点的索引,所以这么写
return cursor != size();
}
//获取下一个结点的操作
public E next() {
//每次遍历每个元素的时候都要知道是否更改了集合类
checkForComodification();
try {
int i = cursor;//获取索引坐标
E next = get(i);//这个get是ArrayList实现的方法
lastRet = i;//记录当前结点的索引
cursor = i + 1;//记录cursor的值,用于下次计算
return next;//返回这个元素
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
//移除方法
public void remove() {
//因为迭代器的remove方法是移除上一个遍历的元素,
if (lastRet < 0)//当上一个遍历的元素被移除且没遍历新的元素抛出异常
throw new IllegalStateException();
checkForComodification();//每次操作集合时都要确定集合是否被更改
try {
//删除集合元素
AbstractList.this.remove(lastRet);
//索引-1
if (lastRet < cursor)
cursor--;
//因为删了这个结点所以lastRet赋值为-1
lastRet = -1;
//因为这操作允许,所以我们更改expectedModCount的值
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
//这个方法就是判断集合是否再迭代过程中被非法更改
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
AbstractList.this.remove(lastRet);
看这句,我们的Itr 是AbstractList的内部类,用外部类.this.方法访问外部类的方法