1. 程式人生 > >java集合原始碼分析(二)---ListIterator與Iterator

java集合原始碼分析(二)---ListIterator與Iterator

吐槽

早上起來刷牙洗臉洗頭髮後,正準備去上課,然後發現今天早上好像不上課emmmmmm,然後就早上繼續看下java集合方面的原始碼了吼吼吼

Iterator

上次好像說過一點這個,然後繼續複習下這個

還是先看下官方文件 在這裡插入圖片描述 在這裡插入圖片描述 然後我們發現這個東西就是個功能很少但很實用的迭代器,但是它也要注意一下幾點:

  • 使用方法iterator()要求容器返回一個Iterator。第一次呼叫Iterator的next()方法時,它返回序列的第一個元素
  • 它只能單向移動
  • 使用next()獲得序列中的下一個元素。
  • 使用hasNext()檢查序列中是否還有元素
  • 使用remove()將迭代器新返回的元素刪除

Iterator 的使用

所有 Collection 的子類都有 iterator() 方法來獲得 Iterator,通過 Iterator 的標準操作方法,可以讓我們不必關心具體集合的型別,從而避免向客戶端暴露出集合的內部結構。

這個我們之前看過Collection 介面的原始碼裡面就有返回一個 Iterator的方法

具體的操作也是很簡單的 先建立一個集合上面的迭代器物件 然後判定是否有下一個 有就返回當前指向的元素//第一次next()是第一個元素

Iterator iterator = list.iterator();
    while (iterator.hasNext()){
        System.
out.println(iterator.next()); }

如果我們不用這個的話,那就for迴圈遍歷唄

for(int i=0; i<集合的大小;i++){  
        // ... 
    } 

這兩種遍歷的區別就是, Iterator體集合型別耦合性弱,複用性更強。缺點就是無法獲取指定的元素,只能挨個遍歷。

而且具體的集合用的時候,它們會實現裡面的方法的

ListIterator

這個還是個介面,繼承於Iterator,比Iterator更加功能強大一點 還是先看下官方的文件 在這裡插入圖片描述 在這裡插入圖片描述 我們發現這個加強版的迭代器比之前多了很多的方法

  • 現在可以前後兩個方向遍歷List了
  • 在遍歷的時候可以修改List的元素
  • 遍歷的時候獲取迭代器的當前的遊標的位置

這塊遊標的是個很神奇的東西,看下文件上面的解釋 在這裡插入圖片描述 這裡的游標位置就是我們說的遊標 在n個元素的列表裡面,遊標的位置在兩個元素的中間,一共有n+1個遊標的位置 看下我畫的3個圖

圖一:初始情況 //初始時它在第 0 個元素之前 在這裡插入圖片描述 圖二:當呼叫next()之後,遊標向後移動一個位置 在這裡插入圖片描述 圖三:當遍歷完所有的元素的時候 在這裡插入圖片描述

看完這三個圖就知道為啥n個元素可以放n+1個位置了emmmm

然後再看下它新加的幾個方法

  • void hasPrevious() 判斷遊標前面是否有元素;
  • Object previous() 返回遊標前面的元素,同時遊標前移一位
  • int nextIndex() 返回遊標後邊元素的索引位置,初始為 0 ;遍歷 N 個元素結束時為 N
  • int previousIndex() 返回遊標前面元素的位置,初始時為 -1
  • void add(E) 在遊標 前面 插入一個元素
  • void set(E) 更新迭代器最後一次操作的元素為 E,也就是更新最後一次呼叫 next() 或者 previous() 返回的元素
  • void remove() 刪除迭代器最後一次操作的元素,注意事項和 set 一樣。

然後我想看下這個介面的具體的實現,然後找啊找,發現了一個抽象類AbstractIndexedListIterator 它先它繼承於UnmodifiableListIterator類,我們進去看下

public abstract class UnmodifiableListIterator<E> extends UnmodifiableIterator<E> implements ListIterator<E> {
    protected UnmodifiableListIterator() {
    }

    /** @deprecated */
    @Deprecated
    public final void add(E var1) {
        throw new UnsupportedOperationException();
    }

    /** @deprecated */
    @Deprecated
    public final void set(E var1) {
        throw new UnsupportedOperationException();
    }
}

進去看了下,這個類就繼承一個類,然後實現了ListIterator介面 我們還是退回去看下AbstractIndexedListIterator的原始碼

abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
    private final int size;//元素的個數
    private int position;//下標的位置

    protected abstract E get(int var1);

    protected AbstractIndexedListIterator(int var1, int var2) {
        Preconditions.checkPositionIndex(var2, var1);
        this.size = var1;
        this.position = var2;
    }

    public final boolean hasNext() {
        return this.position < this.size;//每次都判斷下游標和元素總的個數比較
    }

    public final E next() {
        if (!this.hasNext()) {
            throw new NoSuchElementException();
        } else {
            return this.get(this.position++);//遊標加一,往後移一個位置
        }
    }

    public final int nextIndex() {
        return this.position;//返回遊標後邊元素的索引位置,初始為 0 
    }

    public final boolean hasPrevious() {
        return this.position > 0;//因為遊標的初始值是-1,所以判斷遊標前面是否有元素;
    }

    public final E previous() {
        if (!this.hasPrevious()) {
            throw new NoSuchElementException();
        } else {
            return this.get(--this.position);//返回遊標前面的元素,同時遊標前移一位
        }
    }

    public final int previousIndex() {
        return this.position - 1;//返回遊標前面元素的位置,初始時為 -1
    }
}

但是好像因為List 的子類 ArrayList, LinkedList, Vector 由於底層實現原理不同(陣列,雙向連結串列),具體操作類實現有所不同。 所以,到時候問題具體分析吧