java中的迭代器

Iterator

public interface List<E> extends Collection<E>
public interface Collection<E> extends Iterable<E>

对于Iterable()接口,内部包含了iterator的获取,和forech方法
public interface Iterable{
    Iterator iterator();
    void forech();
}
//Iterator接口
public interface Iterator{
    boolean hasNext;
    E next();
    void remove();
    ···
}
复制代码

Collection接口继承了Iterable接口,而对于每一个数据结构,其内部的遍历方式不一样,因此具体的子类分别定义了本身的iteratornode

public Iterator<E> iterator() {
        return new Itr();
    }
 private class Itr implements Iterator<E>    

复制代码

好比ArrayListz中Iterator的遍历方式bash

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];
        }
复制代码

好比LinkedList中的遍历方式数据结构

在LinkedList中并无实现Iterator接口,而是只实现的ListIterator接口
对于ListIterator接口
public interface ListIterator extends Iterator{
    //除了有iterator所包含的方法,还含有的其它特有方法
    boolean hasPrevious();
    E previous();
    void set();
    void add();
    //也就是说ListIterator 支持修改,添加元素等操做,而且支持倒序遍历
    //咱们看它的一个子类
    private class ListItr implements ListIterator<E> {
        ListItr(int index) {
            // assert isPositionIndex(index);
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }
        //从它的构造方法中能够看出,ListIterator还支持从指定位置遍历
    }
}
//因为LinkedList中为链表结构,因此遍历方式有所不一样
public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();
            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }
复制代码

iterator的remove操做

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();

    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}
咱们知道直接调用List的remove方法会产生错误,由于remove后,后面的元素会向前移动
而在Iterator的remove方法中,调用了List的remove方法后,iterator仍是将cursor=lastRet,实现了对remove
操做的封装。
再看下边一行代码,lastRet=-1,又将lastRet赋值为-1;因此,必须调用了next方法,指向下一个元素后,remove方法
才会有效,否则会抛出IllegalStateException,因此Iterator的remove操做,必然在next操做以后调用。
复制代码

一些思考

众多遍历方式中为何使用Iterator?
对于LinkedList,内部为链表结构。对于下边这种操做ui

LinkedList list = new LinkedList();
for(int i=0;i<list.size;i++){
    list.get(i);
}
复制代码

它的时间复杂度为O(n^2),而若是使用iterator,它的时间复杂度为O(n)
实际上为了提升查找效率,linkedList中采用了简单二分查找元素。this

Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
复制代码

还有就是Iterator的设计思想,它把访问逻辑从不一样类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构,不一样的集合能够在内部实现本身不一样的遍历操做。spa

相关文章
相关标签/搜索