首页 > 编程笔记 > Java笔记

迭代器模式在JDK源码中的应用

本节主要介绍迭代器模式在 JDK 源码中的应用。

<<interface>> Iterator 是 Java 提供的迭代器,可以让某个序列实现该接口来提供标准的 Java 迭代器。也就是说,实现 Iterator 接口就相当于“使用”一个迭代器。

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());
    }
}
从上面代码可以看出,Iterator 接口定义了一些需要子类实现的方法和默认方法。其中包含了两个主要方法,即 hasNext() 和 next() 方法。代码中两个 default 方法是 JDK 1.8 之后才有的接口新特性。JDK 1.8 版本之前接口中不能有方法实体。

另外,我们在学习组合模式时见过 remove() 方法。可以看出迭代器模式和组合模式两者存在一定的相似性,组合模式解决的是统一树形结构各层次访问接口,迭代器模式解决的是统一各集合对象元素遍历接口。虽然它们的适配场景不同,但核心理念是相同的。

接着来看 Iterator 的实现类,以 ArrayList 为例。ArrayList 实现了 List 接口,List 接口继承了 Collection 接口,Collection 接口继承了 Iterable 接口,Iterable 接口中包含了一个 iterator( ) 方法,因此 ArrayList 就需要实现该 iterator( ) 方法。该方法的实现很简单,就是返回一个实现了 Iterator 接口的迭代器实例。

ArrayList 类中的迭代器是以内部类的形式实现的,由于内部类可以直接访问外部类的成员变量,所以该迭代器内部类可以很方便地实现 Iterator 接口中的 hasNext( ) 和 next( ) 方法。ArrayList 中的迭代器内部类名字是 Itr,源码如下所示:
package java.util;

import java.util.function.Consumer;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
transient Object[] elementData;
private int size;

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        ...
    }
    ...
}
Itr 是 ArrayList 中实现了 Iterator 接口的内部类,且在实现 hasNext() 和 next() 方法时,可以很方便地访问 ArrayList 的成员变量 size 和 elementData 数组。

在 ArrayList 内部还有几个迭代器对 Itr 进行了进一步扩展,首先看 ListItr。
private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }
    ...
}
ListItr 内部类增加了 hasPrevious() 方法,主要用于判断是否还有上一个元素。另外,还有 SubList 对子集合的迭代处理。

注意:由于篇幅原因,这里没有列出 ArrayList 中其它几个内部类对 Itr 的进一步扩展,感兴趣的小伙伴可以阅读 ArrayList 类的完整代码。

所有教程

优秀文章