設計模式之迭代器模式
一、java迭代器介紹
1、迭代器接口
在jdk中,與迭代器相關的接口有兩個:Iterator 與 Iterable。
Iterator:迭代器,Iterator及其子類通常是迭代器本身的結構與方法;迭代器是一種模式,它可以使得對於序列類型的數據結構的遍歷行為與被遍歷的對象分離,即我們無需關心該序列的底層結構是什么樣子的。只要拿到
這個對象,使用迭代器就可以遍歷這個對象的內部。
Iterable:可迭代的,那些想用到迭代器功能的其它類,如AbstractList HashMap等,需要實現該接口。
1)Iterator
Java提供一個專門的迭代器<<interface>>Iterator,我們可以對某個序列實現該interface,來提供標准的Java迭代器。Iterator接口實現后的功能是“使用”一個迭代器。
Package java.util; public interface Iterator<E> { //判斷是否存在下一個對象元素 boolean hasNext(); //獲得下一個元素 E next(); //移除下一個元素 void remove(); }
2)Iterable
Java中還提供了一個Iterable接口,Iterable接口實現后的功能是“返回”一個迭代器(Iterator),我們常用的實現了該接口的子接口有: Collection<E>, Deque<E>, List<E>, Queue<E>, Set<E> 等.該接口的iterator()方
法返回一個標准的Iterator實現。
public interface Iterable<T> { Iterator<T> iterator(); }
2、迭代器的實現
看完源碼,我們來看看迭代器是如何使用的:
1) 若類A想要使用迭代器,則它的類聲明部分為 class A implement Iterable
2) 在類A實現中,要實現Iterable接口中的唯一方法:Iterator<T> iterator(); 這個方法用於返回一個迭代器,即Iterator接口及其子類;
3) 在類A中,定義一個內部類S,專門用於實現Iterator接口,定制類A自已的迭代器實現。
如下:
//A實現Iterable接口 class A implement Iterable { //該接口返回一個Iterator對象 Iterator<T> iterator() {...} class S implement Iterator<E> { //上面這個對象會有具體實現的方法 boolean hasNext() {....} E next() {....} void remove() {....} } }
下面我們來看下抽象類AbstractList的jdk源碼
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口實現了Collection<E>, Iterable<E> protected AbstractList() { } ... // 這里返回一個迭代器對象 public Iterator<E> iterator() { return new Itr(); } // Itr內部類實現迭代器 private class Itr implements Iterator<E> { int cursor = 0; int lastRet = -1; int expectedModCount = modCount; // 實現hasNext方法 public boolean hasNext() { return cursor != size(); } // 實現next方法 public E next() { //判斷是否有下一個 checkForComodification(); try { E next = get(cursor); lastRet = cursor++; //返回下一個 return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } // 實現remove方法 public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } //判斷是否有下一個方法 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } }
3、小案例
//實現Iterable class ScanAppleStore implements Iterable<String> { ArrayList<String> appleStore = new ArrayList<String>(); //為初始appleStore賦值 ScanAppleStore() { Collections.addAll(appleStore, "Sweet", "Sour", "Bitter", "litter Sweet", "litter Sour", "litter Bitter"); System.out.print(appleStore); } //重寫Iterator方法 @Override public Iterator<String> iterator() { return new Iterator<String>() { private int i = 0; public boolean hasNext() { if (i < appleStore.size()) { return true; } else { return false; } } public String next() { return appleStore.get(i++); } public void remove() { System.out.print("not defined!"); } }; } public Iterable<String> reverseIterator() { return new Iterable<String>() { public Iterator<String> iterator() { return new Iterator<String>() { private int i = appleStore.size() - 1; public boolean hasNext() { if (i > -1) { return true; } else { return false; } } public String next() { return appleStore.get(i--); } public void remove() { System.out.print("not defined!"); } }; } }; }}
測試類
public class TestIterable { //構造函數初始化 TestIterable() { ScanAppleStore appleTree = new ScanAppleStore(); //采用系統自帶的迭代器 System.out.println("采用系統自帶的迭代器iterator:"); for (String str : appleTree) { System.out.println(str); } System.out.println("======================"); System.out.println("采用自己重新迭代器,讓相反輸出"); //采用自己重新迭代器,讓相反輸出 for (String str : appleTree.reverseIterator()) { System.out.println(str); } } public static void main(String[] args) { TestIterable a = new TestIterable(); } }
運行結果:
[Sweet, Sour, Bitter, litter Sweet, litter Sour, litter Bitter]
采用系統自帶迭代器iterator: Sweet Sour Bitter litter Sweet litter Sour litter Bitter ====================== 采用自己重新迭代器,讓相反輸出: litter Bitter litter Sour litter Sweet Bitter Sour Sweet
二、迭代器模式
1、什么是迭代器模式
GOF給出的定義為:提供一種方法訪問一個容器(container)對象中各個元素,而又不需暴露該對象的內部細節。
Iterator模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明的訪問集合內部的數據。
2、迭代器模式角色組成
1) 迭代器角色(Iterator):迭代器角色負責定義訪問和遍歷元素的接口。
2) 具體迭代器角色(Concrete Iterator):具體迭代器角色要實現迭代器接口,並要記錄遍歷中的當前位置。
3) 容器角色(Container):容器角色負責提供創建具體迭代器角色的接口。
4) 具體容器角色(Concrete Container):具體容器角色實現創建具體迭代器角色的接口——這個具體迭代器角色於該容器的結構相關。
3、案例解析
1)迭代器角色
public interface Iterator { public Object next(); public boolean hasNext(); }
2)具體迭代器角色
public class ConcreteIterator implements Iterator { private List list = new ArrayList(); private int cursor = 0; public ConcreteIterator(List list) { this.list = list; } @Override public Object next() { Object obj = null; if (this.hasNext()) { obj = this.list.get(cursor++); } return obj; } @Override public boolean hasNext() { if (cursor == list.size()) { return false; } return true; } }
3)容器角色
public interface Aggregate { public void add(Object obj); public void remove(Object obj); public Iterator iterator(); }
4) 具體容器角色
public class ConcreteAggregate implements Aggregate { private List list = new ArrayList(); @Override public void add(Object obj) { list.add(obj); } @Override public void remove(Object obj) { list.remove(obj); } @Override public Iterator iterator() { return new ConcreteIterator(list); } }
測試類
public class Client { public static void main(String[] args) { Aggregate ag = new ConcreteAggregate(); ag.add("小明"); ag.add("小紅"); ag.add("小剛"); Iterator it = ag.iterator(); while (it.hasNext()) { String str = (String) it.next(); System.out.println(str); } }}
運行結果
小明
小紅
小剛
4、迭代器優點和缺點
優點:
1)它支持以不同的方式遍歷一個聚合對象。
2)迭代器簡化了聚合類。
3)在同一個聚合上可以有多個遍歷。
4)在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
缺點:
由於迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性。
參考
其實這整篇文章幾乎都來自該篇文章,用參考都不太好意思,哈哈。
想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要么別想,要么多做。中校【7】