標籤:java java設計模式 迭代器 詳解
源碼均以JDK1.8作為參考
1.定義:
Iterator提供一種方法訪問一個容器物件中各個元素,而又不需要暴露對象的內部細節。
2.解析:
通用類圖:
類圖解析:
2.1.Iterator抽象迭代器
抽象迭代器負責定義通用的介面約定,基本都是基於JDK中Iterator介面的定義,源碼如下:
public interface Iterator<E> { boolean hasNext(); E next(); default void remove() { throw new UnsupportedOperationException("remove"); } /* * @since 1.8 */ default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); }}
基本的Iterator都會有hasNext()、next()兩個方法定義的約束,remove()方法提供了在遍曆時刪除容器內部元素,在JDK1.8中加入了default方法forEachRemaining(Consumer action),使得在遍曆時,可以指定一個action進行遍曆。
2.2.Concrete Iterator具體迭代器
Concrete Iterator實現了Iterator介面,並實現了其內部的方法定義,完成具體的迭代,此時的Iterator可以用兩種方式實現。
一種是ConcreteIterator持有具體容器集合的引用,迭代時遍曆集合的元素,常規的Iterator都是按照此種方式實現的。
一種是ConcreteIterator作為容器集合的內部類使用,由於內部類的特殊性,可以隨時獲得外部類的具體實現,完成迭代操作,但是此種實現的Iterator具有依賴性,不可重複使用。
2.3.Aggregate抽象容器
Aggregate抽象容器在Iterator模式中是一個可有可無的存在,定義了容器的一些上層操作,目的是針對多個容器之間關聯性的處理。
2.4.Concrete Aggregate具體容器
具體容器的實現,需要定義其內部結構等,例如ArrayList依賴數組完成元素的存取、HashMap依賴數組、鏈表完成元素的存取等。
3.具體應用:
上面介紹的是Iterator設計模式的通用方式,接下來根據其通用定義完成一個簡單的樣本,通過Iterator模式進行遍曆。
3.1.Iterator抽象迭代器
此迭代器約定使用java.util.Iterator的定義。
3.2.Concrete Iterator具體迭代器
public class ConcreteIterator implements Iterator { private Vector vector = new Vector(); // .. 定義當前遊標 public int cursor = 0; @SuppressWarnings("unchecked") public ConcreteIterator(Vector _vector){ this.vector = _vector; } // .. 判斷是否到達尾部 public boolean hasNext() { if(this.cursor == this.vector.size()){ return false; }else{ return true; } } // .. 返回下一個元素 public Object next() { Object result = null; if(this.hasNext()){ result = this.vector.get(this.cursor++); }else{ result = null; } return result; } // .. 刪除當前元素 public boolean remove() { this.vector.remove(this.cursor); return true; }}
3.3.Aggregate抽象容器
public interface Aggregate { // .. 是容器必然有元素的增加 public void add(Object object); // .. 減少元素 public void remove(Object object); // .. 由迭代器來遍曆所有的元素 public Iterator iterator();}
3.4.Concrete Aggregate具體容器
public class ConcreteAggregate implements Aggregate { // .. 容納對象的容器 private Vector vector = new Vector(); // .. 增加一個元素 public void add(Object object) { this.vector.add(object); } // .. 返回迭代器對象 public Iterator iterator() { return new ConcreteIterator(this.vector); } // .. 刪除一個元素 public void remove(Object object) { this.remove(object); }}
樣本中ConcreteAggregate具體容器內部使用Vector作為結構實現,可以使用如下代碼:
public class Test{ public static void main(String[] args){ ConcreteAggregate ca = new ConcreteAggregate(); Iterator it = ca.iterator(); while(it.hashNext()){ it.next(); } }}
4.forEachRemaining應用:
forEachRemaining是在JDK1.8中加入的介面的default方法,體現了JDK1.8中函數式編程思想
4.1.首先實現Consumer介面
class Action implements Consumer{ @Override public void accept(Object o) { // .. 自己需要處理的事情 }}
4.2.使用Iterator執行個體進行迭代
ConcreteAggregate ca = new ConcreteAggregate();Iterator it = ca.iterator();it.forEachRemaining(new Action());
註:以上是JDK1.8提供的函數式的處理方式,在低版本的JDK中是無法完成此類操作的。
5.注意:
1.儘管Iterator模式是一個很普遍的模式,但是一般的容器都已經提供了其具體實現,除非自己進行定義和實現容器,否則Iterator是沒有必要的,另外需要注意的是在很多JDK容器的實現中,
對於實現了Iterator介面的容器類,有一些實現只是附加功能,像基於簡單數組實現的容器類ArrayList、Vector等,其迭代器速度要比for迴圈的速度慢,而對於一些基於鏈表實現的容器類
LinkedList等,其迭代器的速度要比for迴圈的速度要快,所以在應用時,需要分情況進行具體考慮。
2.對於JDK1.7中新加入的for( : )快速迭代,正式基於Iterator的,只有實現了Iterator介面,並具有相應迭代器的集合容器,才可以使用其進行處理。
3.使用Iterator設計模式的最大理由是因為利用Iterator可以跟實現分開,單獨進行遞增。
4.過度依賴具體類反會提高類與類的耦合度,增加零組件複用的困難。為了降低耦合度,讓類作為零件再利用,必須引進抽象類別和介面的概念。
註:本人是參照《設計模式之禪》和《設計模式》兩本書學習所得,其中加入了自己對於Iterator設計模式的理解,以及對於JDK中源碼的理解。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java設計模式(二) 之 迭代器模式