JDK源碼閱讀之Iterator接口
Iterator接口介紹
對 collection 進行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。Iterator接口也是集合類的頂級接口,全部的集合類都會實現這個接口,直接或間接。
Iterator的方法
Iterator的接口方法比較簡單,主要的是實現是否有下一個,返回當前的對象,刪除一個對象。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
//方法的實現已經在下面的代碼中給出
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Iterator的前身
Iterator迭代器取代了 Java Collections Framework 中的 Enumeration。
爲什麼要取代?官方給出的原因是:
- 迭代器允許調用者利用定義良好的語義在迭代期間從迭代器所指向的 collection 移除元素。
- 方法名稱得到了改進。
通俗點來說就是增加了remove方法和方法名得到了改善(沒有這麼擦長了)
Iterator與Iterable
Iterator和Iterable都是接口。 但是Iterable中有個iterator()方法可以產生Iterator類型的接口,而且大部分接口都是直接實現Iterable接口。
爲什麼不直接實現iterator
因爲Iterator接口的核心方法next()或者hasNext() 是依賴於迭代器的當前迭代位置的。 如果Collection直接實現Iterator接口,勢必導致集合對象中包含當前迭代位置的數據(指針)。 當集合在不同方法間被傳遞時,由於當前迭代位置不可預置,那麼next()方法的結果會變成不可預知。 除非再爲Iterator接口添加一個reset()方法,用來重置當前迭代位置。但即時這樣,Collection也只能同時存在一個當前迭代位置,而Iterable則不然,每次調用都會返回一個從頭開始計數的迭代器,多個迭代器是互不干擾的。
Iterator的錯誤
fail-fast 機制
fail-fast機制在遍歷一個集合時,當集合結構被修改,會拋出Concurrent Modification Exception。
fail-fast會在以下兩種情況下拋出ConcurrentModificationException
- 單線程環境
集合被創建後,在遍歷它的過程中修改了結構。 - 多線程環境
當一個線程在遍歷這個集合,而另一個線程對這個集合的結構進行了修改。
fail-safe機制
fail-safe任何對集合結構的修改都會在一個複製的集合上進行修改,因此不會拋出ConcurrentModificationException
fail-safe機制有兩個問題
- 需要複製集合,產生大量的無效對象,開銷大
- 無法保證讀取的數據是目前原始數據結構中的數據。
迭代器模式
迭代器模式(Iterator),提供一種方法順序訪問一個聚合對象中的各種元素,而又不暴露該對象的內部表示。
閱讀感受
這個接口主要講的是思想,主要是實現一個迭代器。
說明
文章是本人在看完多篇相關博文後,加上自己的的理解寫出來的,本文代表本人觀點,如有錯誤或不同意見,請留言或者聯繫我:[email protected]