JAVA 迭代器

来源:互联网 发布:淘宝蓝魔mos1 编辑:程序博客网 时间:2024/06/05 00:41

迭代器有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如listvector)上遍访的接口,设计人员无需关心容器物件的内容。

各种语言实作Iterator的方式皆不尽同,有些面向对象语言像Java, C#, Python, Delphi都已将Iterator的特性内建语言当中,完美的跟语言整合,我们称之隐式迭代器(implicit iterator),但像是C++语言本身就没有Iterator的特色,但STL仍利用template实作了功能强大的iterator。

Iterator另一方面还可以整合Generator。有些语言将二者视为同一接口,有些语言则将之独立化。

、**************************************************************************************************************

while,do-while和for用来控制循环,有时将它们划分为"迭代语句".语句会重复执行,直到起控制作用的布尔表达式(Boolean-expression)得到"假"的结果为止.

    迭代器(也是一种设计模式)的概念可以用于达成不重写代码就可以应用于不同类型的容器.迭代器是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层的结构(也就是不同容器的类型).此外,迭代器通常被称为"轻量级"对象:创建它的代价小.

    Java的Iterator就是一种迭代器(只能单向移动),它只能用来:
        1,使用方法iterator()要求容器返回一个Iterator.第一次调用Iterator的next()方法时,它返回序列的第一个元素;
        2,使用next()获得序列中的下一个元素;
        3,使用hasNext()检查序列中是否还有元素;
        4,使用remove()将迭代器新近返回的元素删除.

Java代码  收藏代码
  1. package iterator;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.Iterator;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8.   
  9. /* 
  10.  * 通用的迭代器; 
  11.  * 将遍历一个序列的操作与此序列底层结构相分离; 
  12.  * 因为Iterator隐藏了容器底层的结构,所以,IteratorAll.printAll并不知道,也不关心此Iterator是从何容器而来; 
  13.  * 取得一个对象容器,遍历容器以对每个对象执行动作; 
  14.  * 该方法间接使用了Object.toString()方法,因为更具通用性; 
  15.  */  
  16. class IteratorAll {  
  17.     static void printAll(Iterator e) {  
  18.         while (e.hasNext()) {  
  19.             System.out.println("\t" + e.next());  
  20.             /* 
  21.              * 虽然不必要,但仍然可以明确地进行类型转换,效果与调用toString()相同; 
  22.              * System.out.println("\t" + (Integer)e.next()); 
  23.              * 通常Object提供的方法并不能满足需求,所以又要考虑类型转换的问题, 
  24.              * 必须假设你已经取得了某个特定类型的序列的Iterator,并将对结果对象做类型转换(如果类型错误会得到一个运行时异常). 
  25.              */  
  26.         }  
  27.     }  
  28. }  
  29.   
  30. /* 
  31.  * 创建两种不同的容器,一个ArrayList和一个HashMap,均使用Integer填充 
  32.  */  
  33. public class IteratorDemo {  
  34.     public static void main(String[] args) {  
  35.         // 创建ArrayList,并填充Integer类型  
  36.         List<Integer> list = new ArrayList<Integer>();  
  37.         for (int i = 0; i < 10; i++) {  
  38.             list.add(i);  
  39.         }  
  40.         // 创建HashMap,并填充Integer类型  
  41.         Map<Integer, Integer> map = new HashMap<Integer, Integer>();  
  42.         for (int i = 0; i < 10; i++) {  
  43.             map.put(i, i);  
  44.         }  
  45.         System.out.println("List");  
  46.         // 调用上面的通用迭代器,打印ArrayList  
  47.         IteratorAll.printAll(list.iterator());  
  48.         System.out.println("Map");  
  49.         // 对HashMap而言,entrySet()方法生成一个由Map.entry对象组成的Set,Map.entry对象包含映射中每个元素的"键"和"值"  
  50.         // 调用上面的通用迭代器,打印HashMap  
  51.         IteratorAll.printAll(map.entrySet().iterator());  
  52.     }  

/*****************************************************************************************************************************/

迭代这个名词对于熟悉Java的人来说绝对不陌生。我们常常使用JDK提供的迭代接口进行java collection的遍历:

Iterator it = list.iterator();
while(it.hasNext()){
 //using “it.next();”do some businesss logic
}
  而这就是关于迭代器模式应用很好的例子。

  二、 定义与结构

  迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

  从定义可见,迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。

  然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。

  而迭代器模式的出现,很好的解决了上面两种情况的弊端。先来看下迭代器模式的真面目吧。

  迭代器模式由以下角色组成:

  1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。

  2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。

  3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。

  4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

  迭代器模式的类图如下:


  从结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符号“单一职责原则”。

  注意,在迭代器模式中,具体迭代器角色和具体容器角色是耦合在一起的——遍历算法是与容器的内部细节紧密相关的。为了使客户程序从与具体迭代器角色耦合的困境中脱离出来,避免具体迭代器角色的更换给客户程序带来的修改,迭代器模式抽象了具体迭代器角色,使得客户程序更具一般性和重用性。这被称为多态迭代。



/8***************************************************************************************************************/

1.迭代器Iterator
迭代器是一个对象,它的工作是遍历并选择序列中的对象。客户端程序员不关心序列底层的结构。此外,迭代器通常被称为“轻量级”对象:创建它的代价小。因此,经常可以见到对迭代器有些奇怪的限制。
Java 的Iterator 就是迭代器受限制的例子,它只能用来:
1)使用方法 iterator()要求容器返回一个 Iterator。第一次调用Iterator 的next()方法时,它返回序列的第一个元素。
 
2)使用next()获得序列中的下一个元素。
 
3)使用hasNext()检查序列中是否还有元素。
 
4)使用remove()将上一次返回的元素从迭代器中移除。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Cat {
    privateintid;
 
    publicint getId() {
       returnid;
    }
 
    publicvoid setId(int id) {
       this.id = id;
    }
 
    Cat(int i) {
       id = i;
    }
}
 
publicclass Cats {
    publicstaticvoid main(String[] args) {
       List<Cat> cats = new ArrayList<Cat>();
       for (int i = 0; i < 7; i++)
           cats.add(new Cat(i));
       System.out.println("before remove:"+cats.size());
       Iterator e = cats.iterator();
       while (e.hasNext()) {
           //e.remove();//java.lang.IllegalStateException
           System.out.println("Cat id:" + ((Cat) e.next()).getId());
           e.remove();
       }
       System.out.println("after remove:"+cats.size());
    }
}
结果:
before remove:7
Cat id:0
Cat id:1
Cat id:2
Cat id:3
Cat id:4
Cat id:5
Cat id:6
after remove:0
这里必须注意remove()方法的使用,在调用该方法之前必须先调用next()方法。
2.迭代器ListIterator
该迭代器只能用于各种List类的访问。ListIterator可以双向移动。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
publicclass ListIteration {
    publicstaticvoid main(String[] args) {
       List<String> stringList =new ArrayList<String>(Arrays.asList("a","b", "c",
              "d","e"));
       ListIterator<String> it = stringList.listIterator();
       while (it.hasNext())
           System.out.print(it.next() +"," + it.nextIndex() +","
                  + it.previousIndex() +";");
       System.out.println();
       //回溯
       while(it.hasPrevious())
           System.out.print(it.previous()+" ");
       System.out.println();
       System.out.println(stringList);
       it=stringList.listIterator(2);
       while(it.hasNext()){
           it.next();
           it.set("z");
       }
       System.out.println(stringList);
    }
}
结果:
a,1,0;b,2,1;c,3,2;d,4,3;e,5,4;
e d c b a
[a, b, c, d, e]
[a, b, z, z, z]
①next()得到下一个元素;previous()得到前一个元素。
nextIndex()得到下一个元素的索引号;previousIndex()得到前一个元素的索引号。
③hasNext()判断是否还有后继元素;hasPrevious()判断是否还有前驱元素。
④listIterator()得到该集合的迭代器;listIterator(n)得到一个子迭代器,从原集合中第n+1个元素起(注意考虑第一个元素索引号为0)至集合末尾的所有元素组成一个子迭代器。
⑤set(“newElement”)将当前元素替换为newElement。这个方法的调用类似remove()方法,需要先调用next()方法。


原创粉丝点击