Java設計模式百例 - 迭代器模式

本文源碼見:https://github.com/get-set/get-designpatterns/tree/master/iterator

迭代器(Iterator)模式又叫游標(Cursor)模式,通常用于集合類型來提供一種順序訪問其中元素而又不必暴漏集合的內部結構,是一種行為模式。

關于迭代器(Iterator)我想對Java Collection有過接觸的同學就不陌生,所以本文也就無需舉其他例子了,看一下在Java SDK中是如何實現的就好了。

據統(tǒng)計,java.util.ArrayList是Java SDK中使用頻率最高的類。有人說程序就是數據結構+算法,可見數據結構的重要性。我們在日常開發(fā)中,時常跟Java集合中的各種工具類打交道,對于它們,遍歷元素又是家常便飯,比如:

String[] strings = new String[]{"Hello,", "Java", "Design", "Patterns."};
List<String> stringList = Arrays.asList(strings);
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}

輸出即:

Hello, Java Design Patterns. 

其中的Iterator就是迭代器,它有兩個核心方法:

java.util.Iterator.java(不考慮Java8新增內容)

public interface Iterator<E> {
    boolean hasNext();
    E next();
}
  • hasNext()用于判斷是否還有下一個元素;
  • next()用于返回下一個元素,同時“看向”這個元素的再下一個元素。

我們常用的一些Java數據結構工具:

Collection_interfaces.png

Collection是繼承自Iterable,而后者的核心方法就是返回Iterator實例的iterator()方法(不考慮Java8增加的內容的話):

java.lang.Iterable.java

public interface Iterable<T> {
    Iterator<T> iterator();
}

所以我們平時使用的各種不同的List、SetQueue的具體實現,都能返回迭代器以便能夠對它們中的元素進行遍歷。

java.util.ArrayList為例,它的iterator()方法返回的是Iterator的其內部類的實現:

java.util.ArrayList.java

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    // 實際存儲元素的數據
    transient Object[] elementData; 
    // 元素實際個數
    private int size;
    
    ... ...
    
    public Iterator<E> iterator() {
        return new Itr();
    }
    
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        ... ...

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            ... ...
            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];
        }
        ... ...
    } //End of Itr
    ... ...
} //End of ArrayList

其中去掉了一些代碼。ArrayList是一種數組類型的List,其內部采用一個Object[]來保存所有元素,size用來保存一共有多少個元素。

方法iterator()會返回一個內部類Itr,后者實現了Iterator接口的hasNext()next()方法。

既然是迭代遍歷,那么就需要有一個變量能夠記錄遍歷到哪個元素了,這里Itr.cursor就是用來記錄迭代索引的變量。每次調用hasNext()判斷后邊是否還有元素的時候,其實就是比較這個索引的值是否和size相等;每次調用next()返回下一個元素,其實就是返回elementData[cursor]并讓cursor自增以指向下一個元素。

這就是迭代器模式,如果去掉各種接口和類的繼承關系,簡單來說:

iterator-diagram.png

迭代器模式是為集合類的事物服務的,因此類關系就很好說了:一邊是集合,一邊是迭代器,集合能夠返回迭代器,迭代器能夠遍歷集合。 出于面向接口的更加靈活的模式設計,集合和迭代器均有抽象層(接口或抽象類)以及具體實現類。

最后,我們再回頭看一下本文最初的例子:

Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}

這四行就是迭代器模式的典型用法。iterator可能是一個ArrayList返回的,可能是一個HashSet返回的,我們都不care,只要獲取到迭代器,我們就可以“無腦流”一路hasNext() + next(),這就是迭代器的初衷,它為集合封裝了迭代遍歷元素的方法,留給用戶的是一套簡單易用的遍歷接口。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1 場景問題# 1.1 工資表數據的整合## 考慮這樣一個實際應用:整合工資表數據。 這個項目的背景是這樣的,項目...
    七寸知架構閱讀 2,645評論 0 53
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,648評論 0 3
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,728評論 18 399
  • 一.集合框架 1.集合框架(對象數組的概述和使用) a.案例演示 * 需求:我有5個學生,請把這個5個學生的信息存...
    夢游的沙師弟閱讀 627評論 0 1
  • 杜絕團隊中出現負能量。 這是紅線!
    復蘇森林閱讀 111評論 0 1

友情鏈接更多精彩內容