Java設(shè)計模式百例 - 迭代器模式

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

迭代器(Iterator)模式又叫游標(Cursor)模式墨闲,通常用于集合類型來提供一種順序訪問其中元素而又不必暴漏集合的內(nèi)部結(jié)構(gòu)代咸,是一種行為模式玉锌。

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

據(jù)統(tǒng)計讲竿,java.util.ArrayList是Java SDK中使用頻率最高的類翅娶。有人說程序就是數(shù)據(jù)結(jié)構(gòu)+算法,可見數(shù)據(jù)結(jié)構(gòu)的重要性昼浦。我們在日常開發(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新增內(nèi)容)

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

我們常用的一些Java數(shù)據(jù)結(jié)構(gòu)工具:

Collection_interfaces.png

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

java.lang.Iterable.java

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

所以我們平時使用的各種不同的List熊经、SetQueue的具體實現(xiàn),都能返回迭代器以便能夠?qū)λ鼈冎械脑剡M行遍歷。

java.util.ArrayList為例镐依,它的iterator()方法返回的是Iterator的其內(nèi)部類的實現(xiàn):

java.util.ArrayList.java

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    // 實際存儲元素的數(shù)據(jù)
    transient Object[] elementData; 
    // 元素實際個數(shù)
    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是一種數(shù)組類型的List,其內(nèi)部采用一個Object[]來保存所有元素馋吗,size用來保存一共有多少個元素焕盟。

方法iterator()會返回一個內(nèi)部類Itr,后者實現(xiàn)了Iterator接口的hasNext()next()方法宏粤。

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

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

iterator-diagram.png

迭代器模式是為集合類的事物服務(wù)的繁莹,因此類關(guān)系就很好說了:一邊是集合,一邊是迭代器特幔,集合能夠返回迭代器咨演,迭代器能夠遍歷集合。 出于面向接口的更加靈活的模式設(shè)計蚯斯,集合和迭代器均有抽象層(接口或抽象類)以及具體實現(xiàn)類薄风。

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

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

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炫惩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子阿浓,更是在濱河造成了極大的恐慌他嚷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異筋蓖,居然都是意外死亡卸耘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門粘咖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚣抗,“玉大人,你說我怎么就攤上這事瓮下『舱。” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵讽坏,是天一觀的道長锭魔。 經(jīng)常有香客問我,道長路呜,這世上最難降的妖魔是什么迷捧? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮胀葱,結(jié)果婚禮上漠秋,老公的妹妹穿的比我還像新娘。我一直安慰自己抵屿,他們只是感情好膛堤,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晌该,像睡著了一般肥荔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朝群,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天燕耿,我揣著相機與錄音,去河邊找鬼姜胖。 笑死誉帅,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的右莱。 我是一名探鬼主播蚜锨,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慢蜓!你這毒婦竟也來了亚再?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤晨抡,失蹤者是張志新(化名)和其女友劉穎氛悬,沒想到半個月后则剃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡如捅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年棍现,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镜遣。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡己肮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悲关,到底是詐尸還是另有隱情朴肺,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布坚洽,位于F島的核電站戈稿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏讶舰。R本人自食惡果不足惜鞍盗,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跳昼。 院中可真熱鬧般甲,春花似錦、人聲如沸鹅颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堪伍。三九已至锚烦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帝雇,已是汗流浹背涮俄。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尸闸,地道東北人彻亲。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像吮廉,于是被迫代替她去往敵國和親苞尝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 工資表數(shù)據(jù)的整合## 考慮這樣一個實際應(yīng)用:整合工資表數(shù)據(jù)宦芦。 這個項目的背景是這樣的宙址,項目...
    七寸知架構(gòu)閱讀 2,547評論 0 53
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,497評論 0 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法踪旷,類相關(guān)的語法曼氛,內(nèi)部類的語法,繼承相關(guān)的語法令野,異常的語法舀患,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 一.集合框架 1.集合框架(對象數(shù)組的概述和使用) a.案例演示 * 需求:我有5個學生,請把這個5個學生的信息存...
    夢游的沙師弟閱讀 549評論 0 1
  • 杜絕團隊中出現(xiàn)負能量气破。 這是紅線聊浅!
    復(fù)蘇森林閱讀 69評論 0 1