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

相關文章
相關標籤/搜索