懷着莊嚴而聖神的心情,今天打開了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的辨析》