当前位置:   article > 正文

Java设计模式(七)—— 迭代器模式_java迭代器模式

java迭代器模式

        迭代器模式定义如下:提供一种方法访问一个容器对象中的各个元素,而又勿需暴露该对象的内部细节,是一种只应用于容器对象遍历的设计模式。

适合迭代器模式的情景如下:

  • 遍历集合对象,不需要知道对象在集合中的存储方式
  • 用户可以同时使用多个迭代器遍历一个集合

一、问题的提出

        在计算机程序设计中,经常会用到各种各样的容器,如数组、链表、集合、映射等。在容器的各种操作中,元素遍历时最常见的操作之一。不同类型的容器,遍历方法也不同。以学生数组和链表元素遍历功能为例,代码如下:

(1)学生类

  1. public class Student {
  2. String sno;
  3. String name;
  4. public Student(String sno, String name) {
  5. this.sno = sno;
  6. this.name = name;
  7. }
  8. }

(2)学生数组容器类

该类是泛型数组容器类,提供遍历功能的基础方法是:获得数组大小size()方法,获得数组某下标位置元素对象get()方法。

  1. public class MyArray<T> {
  2. T t[];
  3. //传入一个数组
  4. MyArray(T t[]) {
  5. this.t = t;
  6. }
  7. T get(int n) {
  8. if (n < t.length) {
  9. return t[n];
  10. } else {
  11. return null;
  12. }
  13. }
  14. int size() {
  15. return t.length;
  16. }
  17. }

(3)链表节点类

        该类是任意泛型T的链表节点类,成员变量next代表指向的下一个Node节点的地址。

  1. public class Node<T> {
  2. T t;
  3. Node next;
  4. Node(T t) {
  5. this.t = t;
  6. }
  7. void setNext(Node next) {
  8. this.next = next;
  9. }
  10. Node getNext() {
  11. return next;
  12. }
  13. T getT() {
  14. return t;
  15. }
  16. }

(4)链表容器类

        对链表容器来说,最重要的就是首元素,因此将其定义为成员变量head,getNext()方法是遍历链表最重要的基础方法,功能是返回形参节点node的后继节点。

  1. public class MyLink<T> {
  2. Node<T> head;
  3. MyLink(Node<T> head) {
  4. this.head = head;
  5. }
  6. public Node<T> getHead() {
  7. return head;
  8. }
  9. Node<T> getNext(Node<T> node) {
  10. return node.getNext();
  11. }
  12. }

(5)遍历数组及链表的测试类

  1. public class Test {
  2. public static void main(String[] args) {
  3. System.out.println("数组测试:");
  4. //初始化一个学生数组
  5. Student s[] = new Student[2];
  6. s[0] = new Student("1001","zhangyin");
  7. s[1] = new Student("1002","siminmin");
  8. //将该学生数组传入MyArray
  9. MyArray<Student> myArray = new MyArray<>(s);
  10. for (int i = 0; i < myArray.size(); i++) {
  11. //返回数组下标对应的学生元素
  12. Student student = myArray.get(i);
  13. System.out.println(student.sno+"\t"+student.name);
  14. }
  15. System.out.println("链表测试:");
  16. //初始化另一个学生数组
  17. Student s1[] = new Student[3];
  18. s1[0] = new Student("1003","yinyin");
  19. s1[1] = new Student("1004","minmin");
  20. s1[2] = new Student("1005","sisi");
  21. //将每个学生元素放入node中
  22. Node<Student> node1 = new Node<>(s1[0]);
  23. Node<Student> node2 = new Node<>(s1[1]);
  24. Node<Student> node3 = new Node<>(s1[2]);
  25. node1.next = node2;
  26. node2.next = node3;
  27. MyLink<Student> myLink = new MyLink<>(node1);
  28. Node<Student> cur = myLink.getHead();
  29. while (cur != null) {
  30. Student student = cur.getT();
  31. System.out.println(student.sno+"\t"+student.name);
  32. cur = cur.getNext();
  33. }
  34. }
  35. }

测试结果:

  1. 数组测试:
  2. 1001 zhangyin
  3. 1002 siminmin
  4. 链表测试:
  5. 1003 yinyin
  6. 1004 minmin
  7. 1005 sisi

思考:

从上面例子可以看出,数组和链表的遍历方式是不同的,那么能否有一种容器元素遍历方式,对各种容器而言都是一致的,且与容器的性质无关呢?这就用到迭代器遍历的思想。

二、迭代器模式

        迭代器模式,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部元素的表示。迭代器模式把在元素之间游走的责任交给了迭代器,而不是聚合对象。

        JDK中迭代器模式是很成熟的,它应用在许多容器中,下面代码体现了迭代器在Vector、LinkedList、Set容器中的遍历应用,从中可以更清晰地看出迭代器的特点。

Vector容器的特点是内存空间是线性、连续的;

LinkedList容器的特点是链式结构;

Set容器的特点是树形结构

通过下面代码可以知道,容器元素的遍历与具体的容器是无关的。 

  1. public class Test2 {
  2. public static void traverse(Collection<String> collection) {
  3. Iterator<String> it = collection.iterator();
  4. while (it.hasNext()) {
  5. String str = it.next();
  6. System.out.println(str);
  7. }
  8. }
  9. public static void main(String[] args) {
  10. Vector<String> vector = new Vector<>();
  11. vector.add("aaa");
  12. vector.add("bbb");
  13. vector.add("ccc");
  14. System.out.println("Vector traverse:");
  15. traverse(vector);
  16. System.out.println();
  17. LinkedList<String> linkedList = new LinkedList<>();
  18. linkedList.add("ddd");
  19. linkedList.add("eee");
  20. linkedList.add("fff");
  21. System.out.println("LinkedList traverse:");
  22. traverse(linkedList);
  23. System.out.println();
  24. Set<String> set = new HashSet<>();
  25. set.add("ggg");
  26. set.add("hhh");
  27. set.add("iii");
  28. System.out.println("Set traverse:");
  29. traverse(set);
  30. System.out.println();
  31. }
  32. }

测试结果:

  1. Vector traverse:
  2. aaa
  3. bbb
  4. ccc
  5. LinkedList traverse:
  6. ddd
  7. eee
  8. fff
  9. Set traverse:
  10. ggg
  11. iii
  12. hhh

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/512796
推荐阅读
相关标签
  

闽ICP备14008679号