迭代器模式-統一集合的遍歷方式


公號:碼農充電站pro
主頁:https://codeshellme.github.io

今天來介紹迭代器模式Iterator Design Pattern),它還有另一個名字,叫作游標模式Cursor Design Pattern)。

1,遍歷集合元素

現在的高級語言(比如 C++JavaPython 等)都支持很多種集合(比如 ListMapSet 等),用於存儲對象。

同時這些高級語言也都原生支持了迭代器,這使得遍歷集合變得非常簡單。

下面我們來看下,如果不使用迭代器,如何遍歷集合。

Java ArrayList 為例,創建 list,並加入 5 個元素:

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

用 for 循環遍歷 list

for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

如果不用迭代器,只能使用 get 方法,將集合中的元素一個個取出。

如果使用迭代器遍歷元素,就可以像下面這樣:

Iterator<Integer> i = list.iterator();
while (i.hasNext()) {
    System.out.println(i.next());
}

先用 iterator 方法返回迭代器,再用 hasNext 方法查看迭代器中是否還有元素,如果有元素則用 next 方法取出元素。

更簡單的方式是使用 forEeah 循環:

for (Object i: list) {
    System.out.println(i);
}

forEach 循環(對迭代器的一種包裝)是 Java 5 中引入的遍歷集合的方式,這種方式不再需要獲取迭代器,甚至不需要知道所遍歷的是哪種數據結構,也不需知道其中存儲的是什么類型的數據。

Java 集合框架與迭代器

Java 中的 SetListQueue 都實現了 Collection 接口,該接口中的 iterator 方法返回一個迭代器,用於遍歷集合中的元素。

這使得所有的 Collection 對象的遍歷都變得非常簡單,使用 forEach 循環即可:

for (Object o: collection) {
    // 遍歷元素
}

2,迭代器模式

迭代器模式提供了一種方法,用於遍歷集合對象中的元素,而又不暴露其內部的細節

一般的迭代器都要實現一個迭代器接口,該接口至少包含兩個方法,即 hasNextnext

public interface Iterator {
    boolean hasNext();
    Object next();
}

hasNext 方法用於查看集合中是否還有下一個元素;next 方法用於返回集合中的下一個元素,並移動指向元素的游標。

Java 中的 Iterator 接口中還有一個 remove 方法,其實這個方法的必要性並不大,所以它的默認實現是拋出 UnsupportedOperationException 異常。因此,對於 remove 方法,不需要給予太多的關注。

這使得每個集合中的元素的訪問方式都是統一的。

一個完整的迭代器模式一般會包含集合迭代器兩部分,為了達到基於接口而非實現編程的原則,還抽象出了兩個接口,其類圖如下:

在這里插入圖片描述

Collection 中的 iterator 方法用於返回當前對象的迭代器,從而遍歷集合中的元素。

迭代器模式將集合對象的遍歷操作從集合類中拆分出來,放到迭代器類中,使得兩者的職責更加單一。

這其實用到了單一職責原則:一個類應該只有一個引起變化的原因。

3,迭代器不支持增刪

迭代器的目的是為了方便元素的遍歷,而如果在遍歷的過程中增刪元素,則會導致元素重復遍歷或者遍歷不到

下面來看下這種錯誤是如何產生的。

假設一個列表中有 abcd 四個元素,我們從前往后遍歷。剛開始時,游標 cursor 指向 a

在這里插入圖片描述

當遍歷到 b 時,cursor 指向 b

在這里插入圖片描述

遍歷時刪除元素

如果此時將 a 元素刪除,那么所有其它元素都會前移一個位置:

在這里插入圖片描述

從而,這時的游標就會指向 c,這就會導致 b 沒有被遍歷到。

遍歷時增加元素

如果在遍歷到 b 的時候,在表頭增加一個元素 x,那么所有的元素都會后移一個位置:

在這里插入圖片描述

從而,這時的游標依然是指向 a,這就會導致 a 被重復遍歷了。

因此,在使用迭代器遍歷元素的時候都會禁止增刪元素。

Java 如何禁止增刪元素

為了禁止在遍歷時增刪元素,Java 的做法是,在遍歷元素時會進行 checkForXXX 操作,目的是檢查是否有元素增刪,如果有增刪的情況,則拋出異常。

4,總結

迭代器模式是為了方便元素的遍歷,它統一了集合的遍歷方式。它將元素的遍歷操作從集合中拆分出來,從而使得兩者得以解耦。

大部分高級語言都原生支持迭代器,這使得開發人員可以專注於業務實現,而不用過多的關心底層實現。

如果在迭代器的遍歷過程中增刪元素,則會導致元素的遍歷發生錯誤,因此迭代器中一般不支持增刪元素。

(本節完。)


推薦閱讀:

裝飾者模式-動態的包裝原有對象的行為

命令模式-將請求封裝成對象

適配器模式-讓不兼容的接口得以適配

外觀模式-簡化子系統的復雜性

模板方法模式-封裝一套算法流程


歡迎關注作者公眾號,獲取更多技術干貨。

碼農充電站pro


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM