迭代器模式遍歷集合的成熟模式,迭代器模式的關鍵是將遍歷集合的任務交給一個叫做迭代器的對象,它的工作時遍歷並選擇序列中的對象,而客戶端程序員不必知道或關心該集合序列底層的結構。
迭代器模式的結構中包括四種角色。
一、集合:一個接口,規定了具體集合需要實現的操作。
二、具體集合:具體集合石實現了集合接口的一個實例,具體的集合按照一定的結構存儲對象。具體集合應該有一個方法,該方法返回一個針對該集合的具體迭代器。
三、迭代器:一個接口,規定了遍歷具體集合的方法,比如next()方法。
四、具體迭代器:實現了迭代器接口的類的實例。具體迭代器在實現迭代器接口所規定的遍歷集合的方法時,比如next()方法,要保證首次調用將按着集合的數據結構找到該集合的一個對象,並且每當找到集合中的一個對象,立即根據該集合的存儲結構得到待遍歷的后繼對象的引用,並保證一次調用next()方法可以遍歷集合。
下列應用程序中,使用了迭代器模式中所涉及的類。該應用程序模擬點鈔,使用HashSet類的實例,即一個集合模擬保險箱HashSet類的實例調用iterator()方法返回一個迭代器,用該迭代器模擬點鈔機,而且在點鈔過程中銷毀假鈔。
1 package com.iterator; 2 3 import java.util.Collection; 4 import java.util.HashSet; 5 import java.util.Iterator; 6 7 public class Application { 8 public static void main(String[] args) { 9 int n = 20; 10 int sum = 0; 11 Collection<RenMinMony> set = new HashSet<RenMinMony>();//集合對象 12 for(int i=1;i<=n;i++){ 13 if(i==n/2 || i==n/5 || i==n/6){ 14 set.add(new RenMinMony(100,false)); 15 }else{ 16 set.add(new RenMinMony(100,true)); 17 } 18 } 19 Iterator<RenMinMony> iterator = set.iterator(); 20 int jia = 0, zhen = 0; 21 System.out.println("保險箱共有"+set.size()+"張人民幣!"); 22 int k = 0; 23 while(iterator.hasNext()){ 24 RenMinMony money = iterator.next(); 25 k++; 26 if(money.isTure() == false){ 27 System.out.println("第"+k+"張是假幣,被銷毀"); 28 iterator.remove();//移除掉最近一次本next()返回的對象 29 k++; 30 } 31 } 32 System.out.println("保險箱現有真人民幣"+set.size()+"張,總價值是:"); 33 iterator = set.iterator(); 34 while(iterator.hasNext()){ 35 RenMinMony money = iterator.next(); 36 sum = sum + money.getValue(); 37 } 38 System.out.println(sum+"元"); 39 } 40 } 41 42 class RenMinMony{ 43 int value; 44 private boolean isTure; 45 public RenMinMony(int value,boolean isTure) { 46 this.value = value; 47 this.isTure = isTure; 48 } 49 public int getValue() { 50 return value; 51 } 52 public boolean isTure() { 53 return isTure; 54 } 55 }
運行結果如下:
保險箱共有20張人民幣!
第6張是假幣,被銷毀
第12張是假幣,被銷毀
第17張是假幣,被銷毀
保險箱現有真人民幣17張,總價值是:
1700元
迭代器優點之一:能夠快速遍歷集合。
看下面的例子就能感覺出它的快速優勢:
1 package com.iterator; 2 3 import java.util.Iterator; 4 import java.util.LinkedList; 5 6 public class TestSpeed { 7 public static void main(String[] args) { 8 LinkedList<String> list = new LinkedList<String>(); 9 for (int i = 0; i < 60000; i++) { 10 list.add("speed"+i); 11 } 12 Iterator<String> iter = list.iterator(); 13 long startTime = System.currentTimeMillis(); 14 while(iter.hasNext()){ 15 String te = iter.next(); 16 } 17 long endTime = System.currentTimeMillis(); 18 long result = endTime - startTime; 19 System.out.println("使用迭代器遍歷集合的時間:"+result+"毫秒"); 20 startTime = System.currentTimeMillis(); 21 for (int i = 0; i < list.size(); i++) { 22 String te = list.get(i); 23 } 24 endTime = System.currentTimeMillis(); 25 result = endTime - startTime; 26 System.out.println("使用get()遍歷集合的時間:"+result+"毫秒"); 27 } 28 }
迭代器的優點之二:能夠實現不重新代碼就可以應用於不能的容器類型。比如說原先用的事List編碼的,但是后來想把相同的代碼用於Set,用迭代器將會顯得特別方便。
1 package com.iterator; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.Iterator; 6 import java.util.LinkedList; 7 import java.util.List; 8 import java.util.Set; 9 10 public class IteratorTest { 11 public static void main(String[] args) { 12 //List<String> conn = new ArrayList<String>(); 13 Set<String> conn = new HashSet<String>(); 14 conn.add("aaa"); 15 conn.add("aaa"); 16 conn.add("bbb"); 17 conn.add("ccc"); 18 Iterator<String> iterator = conn.iterator(); 19 while(iterator.hasNext()){ 20 String a = iterator.next(); 21 System.out.println(a); 22 } 23 } 24 }
下面講一講ListIterator
ListIterator是一個更加強大的Iterator的子類型,但是它只能用於各種List類的訪問。盡管Iterator只能向前移動,但是ListIterator可以雙向移動。他還可以產生相對於迭代器在列表中指向當前位置的前一個和后一個元素的索引,並且還可以用set()方法替換掉它訪問過的最后一個元素。你可以通過調用listIterator()方法產生一個指向List開始處的ListIterator,並且還可以通過調用listIterator(n)方法創建一個一開始就指向列表索引為n的元素處的ListIterator。下面的示例演示了所有這些功能:
1 package com.iterator; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.ListIterator; 6 7 public class ListIteratorTest { 8 9 public static void main(String[] args) { 10 List<Integer> list1 = new ArrayList<Integer>(); 11 for (int i = 0; i <= 10; i++) { 12 list1.add(i); 13 } 14 List<Integer> list2 = new ArrayList<Integer>(); 15 for (int i = 0; i <= 10; i++) { 16 list2.add(i); 17 } 18 //現在將list1的元素反序插入到list2中 19 ListIterator<Integer> it = list1.listIterator(list1.size()); 20 while(it.hasPrevious()){ 21 list2.add(it.previous()); 22 } 23 //遍歷list2 24 it = list2.listIterator(); 25 while(it.hasNext()){ 26 System.out.println(it.next()); 27 } 28 } 29 }