Java中集合類源碼分析(1)-----Iterable和Iterator源碼分析

懷着莊嚴而聖神的心情,今天打開了Java8的源碼.以前用了不少集合內的東西,但也只是會用(當然還有許多不知道的),對於一些集合的選擇,原理實現是不求甚解的,也看了不少介紹其結構層次,所以今天決定自己來研讀研讀.新手輕噴…沒人看我就留着以後自己慢慢看了(笑)
Java集合主要可以劃分爲4個部分:List列表、Set集合、Map映射、工具類(Iterator迭代器、Enumeration枚舉類、Arrays和Collections)
本文從最熟悉的Collection開始,先找其父類(接口),然後向下,挨個問候哈哈哈~
本篇文章是該系列文的第一篇.
工具:eclipse和Java8英文API手冊,有道詞典

1.Collection接口的父接口—–Iterable接口

打開Collection.class發現其作爲一個接口,繼承自Iterable接口

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

/**
 * 實現了這個接口,就可以使這個對象成爲 "for-each"循環語句的目標
 * 也就是說實現了這個接口,就可用 "for-each"語句,這也是Iterable實現的特徵
 */
public interface Iterable<T> {

     //返回一個在這個類型<T>裏的元素的迭代器
    Iterator<T> iterator();

    /**
     *對Iterable的類中的每一個元素執行給定的操作,直到所有的元素都處理過了或者動作拋出了異常
     *除非是被實現類特別指定,否則動作將以迭代的順序進行(如果迭代順序被指定了的話)
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);//驗證action是否爲null,是的話則拋出NullPointerException  
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     *(下面這個Spliterator是Java8纔有的,這個名字代表"可分迭代器"(splitable iterator)。
     *和Iterator一樣, Spliterator也用於遍歷數據源中的元素,但它是爲了並行執行而設計的。能力有限,以後再說吧)
     *
     *創建一個被這個Iterable接口描述的元素上Spliterator。 
     *  
     * 默認實現從iterable的Iterator中創建一個早期綁定的spliterator。這個spliterator 
     * 繼承iterable的iterator的fail-fast性質。 
     *  
     * 默認實現應該總是被重寫。被默認實現返回的spliterator擁有不好分解能力,是不依據指定 
     * 大小定製的,而且不報告任何spliterator的性質。實現類差不多總是能提供更好的實現。 
     *
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

2.Iterable中一個重要”組成部分”——Iterator接口

發現Iterable接口中有一個返回Iterator的方法,當然要看一看啦~

package java.util;

import java.util.function.Consumer;

/**
 * An iterator over a collection.  {@code Iterator} takes the place of
 * {@link Enumeration} in the Java Collections Framework.  Iterators
 * differ from enumerations in two ways:
 *是一個在集合上的迭代器.迭代器在Java集合框架中替代了Enumeration的位置.
 *Iterators與enumeration的不同主要有兩點:
 *  (1)迭代器允許在迭代過程中從這個集合中移除元素
 *  (2)方法名稱有所改進
 *
 *參數: 被迭代的元素的類型
 */
public interface Iterator<E> {
    /**
     *返回boolean,判斷迭代器中是否還有元素()換句話說,如果返回true,則next()將返回一個元素而不是拋出一個異常
     *
     * 返回true,如果還有元素
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *返回迭代器中的下一個元素
     * @return 迭代器中的下一個元素 E類型
     * @throws NoSuchElementException,當迭代器中沒有元素時拋出
     */
    E next();

    /**
     * 從這個collection中移除被迭代器迭代的最後一個元素.
     * 這個方法可以在每次調用next()後調用一次.
     * 當迭代器運行時,這個collection被除這個方法的其他方式修改的話,迭代器的行爲是不被指定的.
     * 
     * 默認實現拋出UnsupportedOperationException的一個實例,不執行任何動作。 
     *
     *當next()未被調用時,或者remove()方法 已經被最後一個next()用掉後,拋出IllegalStateException
     *(這意味着:remove()可以刪除最後一次看到的元素,不能一次調用兩次remove())
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * 驗證action是否爲空,是的話拋出NonPointerException
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

關於Iterable和Iterator的聯繫與區別

1.通過源碼我們發現Iterable接口裏面有一個返回Iteartor的方法,其返回一個Iterator類型的對象(或者說實現了Iterator接口的對象)。那麼也就是說,實現了Iterable接口的類可以通過iterator()方法得到一個迭代器,然後後可以調用Iterator類型的方法(上文提到的next(),remove等)
2.還發現實現了Iterable接口的類可以擁有增強的for.這一點只是實現了Iterator的類還不行.
那麼可以想象,如果這些集合直接實現Iterator接口,則會導致集合對象中包含當前迭代位置的數據(指針)。當集合在不同方法間進行傳遞的時候,由於當前迭代位置不可知,所以next()的結果也不可知。除非再爲Iterator接口添加一個reset()方法,用來重置當前迭代位置。 而當實現Iterable則不然,每次調用都返回一個從頭開始的迭代器,各個迭代器之間互不影響。—–TangowL《Java中Iterable和Iterator的辨析》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章