迭代器模式
迭代器模式遍历集合的成熟模式,迭代器模式的关键是将遍历集合的任务交给一个叫做迭代器的对象,它的工作时遍历并选择序列中的对象,而客户端程序员不必知道或关心该集合序列底层的结构。
迭代器模式的结构中包括四种角色。
一、集合:一个接口,规定了具体集合需要实现的操作。
二、具体集合:具体集合石实现了集合接口的一个实例,具体的集合按照一定的结构存储对象。具体集合应该有一个方法,该方法返回一个针对该集合的具体迭代器。
三、迭代器:一个接口,规定了遍历具体集合的方法,比如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 }