Iterator迭代器

Iterator接口

Iterator接口含有3个方法

public interface Iterator{
    E next();
    boolean hasNext();
    void remove();
}
  • next()

    如果到达了集合末尾,将会抛出NoSuchElementException,因此,一般调用next()前要调用hasNext()

    然而,跟C++STL的迭代器不同,STL中的迭代器是根据数据索引建模的,道理跟索引i对应a[i]元素一样,而Java迭代器被认为是位于两个元素之间,当调用next时,迭代器就越过下一个元素,并返回越过的元素的引用,有点类似“消费掉”的意思。

  • 删除元素

    删除上次调用next方法时返回的元素,next方法和remove方法的调用互相依赖,如果调用remove之前没有调用next是不合理的,会抛出IllegalStateException(set方法同理)

ListIterator接口

相比于Iterator,还包括add,previous,hasPrevious方法,LinkedList类就实现了此接口

previous,hasPrevious和next,hasNext同,只是一个顺着一个逆着遍历,当然,在调用remove的时候,删除的是越过的元素,而并不是说一定为迭代器左边的元素

java中的链表都是双向链表,所以会有previous,hasPrevious,add方法仅针对资源有序的集合,也就是说,add方法将会添加到当前的iterator后面,如果iterator刚创建,也就是在头结点前,此时调用add则此新节点将会变成头结点

对于set等无序集合,在iterator接口是实现add方法就没有意义,所以Collection拓展的是Iterator接口,没有包括add方法

Collection

Collection接口拓展了Iterator接口,也就是说所有的

foreach

foreach循环可以和任何实现了Iterable接口的对象一起工作,这个接口只有一个方法

public interface Iterable{
    Iterator iterator();
}

AbstractList中Iterator的实现

在iterator接口中返回了一个内部类Itr

private class Itr implements Iterator {
    //下一个元素的索引位置
    int cursor = 0;

    //上一个元素的索引位置,这个值将会变成-1在调用remove()之后
    int lastRet = -1;

    /**
     * The modCount value that the iterator believes that the backing
     * List should have.  If this expectation is violated, the iterator
     * has detected concurrent modification.
     */
    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();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

next()的实现是通过get(cursor)然后cursor++,通过这样实现遍历

而在remove()中,有这么一句“expectedModCount = modCount”,这是一种称为“快速失败”的机制,提供了迭代过程中集合的安全性,也就是说迭代过程中不允许修改集合

modCount记录修改此列表的次数:包括改变列表的结构,改变列表的大小,打乱列表的顺序等使正在进行迭代产生错误的结果。

每次增删操作都有modCount++,通过和expectedModCount的对比,迭代器可以快速的知道迭代过程中是否存在list.add()类似的操作,存在的话快速失败!

然而,需要注意的是,仅仅设置元素的值并不是结构的修改

你可能感兴趣的:(Iterator迭代器)