文章目录
GOF定义
迭代器模式(别名: 游标)
提供一种方法顺序访问一个聚合对象中的各个元素, 而又不需要暴露该对象的内部表示
概述
链表和散列表等数据结构都可以存放若干个对象的集合, 其区别是按着不同的方式来存储对象. 我们希望无论何种集合, 应当允许程序以一种统一的方式遍历集合中的对象, 而不需要知道这些对象在集合中是如何表示存储的.
迭代器模式是遍历集合的成熟模式, 迭代器模式的关键是将遍历集合的任务交给一个称作迭代器的对象.
迭代器模式的优点和适合使用迭代器模式的情景
优点
- 用户使用迭代器访问集合中的对象, 而不需要知道这些对象在集合中是如何表示及存储的.
- 用户可以同时使用多个迭代器遍历一个集合.
适合使用观察者模式的情景
- 让用户访问一个集合中的对象, 但是不想暴露对象在集合中的存储结构
- 希望对遍历不同的集合提供一个统一的接口
模式的结果与使用
四种角色
集合(Aggregate)
这里使用 java.util 包中的 Collection 接口作为模式中的集合对象. Java 所有的集合都实现了该接口.
具体集合(ConcreteAggregate)
这里使用 java.util 包中的 HashSet 类的实例作为模式中的具体集合对象
迭代器(Iterator)
在本案例中, 使用的迭代器是 java.util 包中的 Itreator 接口, 该接口有:
- boolean hasNext()
- Object next()
- void remove()
三个方法. 迭代器通过调用 next() 方法依次返回集合中的对象, 通过调用 hasNext() 方法判断集合中是否还有对象未被 next() 方法返回, 调用 remove() 方法 从集合中删除最近一次调用 next() 方法返回的对象.
具体迭代器(ConcreteIterator)
HashSet 创建的集合可以使用 iterator() 方法返回一个实现 Itreator 接口类的实例, 即一个具体的迭代器
案例一 :简单迭代器模式
package com.beyond.cwq.iterator;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
class RenMinMoney {
private int value;
private boolean isTrue;
public RenMinMoney(int value, boolean b) {
this.value = value;
this.isTrue = b;
}
public int getValue() {
return value;
}
public boolean getIsTrue() {
return isTrue;
}
}
public class IteratorDemo {
public static void main(String[] args) {
int n = 20;
int sum = 0;
Collection<RenMinMoney> set = new HashSet<RenMinMoney>(); // 集合对象
for (int x = 1; x <= n; x++) {
if (x == n / 2 || x == n / 5 || x == n / 6) {
set.add(new RenMinMoney(100, false));
} else {
set.add(new RenMinMoney(100, true));
}
}
Iterator<RenMinMoney> iterator = set.iterator(); // 迭代器
int jia = 1, zhen = 1;
System.out.println("保险箱共有" + set.size() + "张人民币");
int k = 0;
while (iterator.hasNext()) {
RenMinMoney money = iterator.next();
k++;
if (money.getIsTrue() == false) {
System.out.println("第" + k + "张是假币~被销毁");
iterator.remove();
}
}
System.out.println("保险箱现在有人民币" + set.size() + "张, 总价值是: ");
iterator = set.iterator();
while (iterator.hasNext()) {
RenMinMoney money = iterator.next();
sum = sum + money.getValue();
}
System.out.println(sum + "元");
}
}
迭代器的 next() 方法 与 集合的get(int index) 方法
某些集合根据其数据存储结构和所具有的操作也会提供返回集合中对象的方法, 例如 LinkedList(ArrayList) 类中的 get(int index) 方法将返回当前链表(数组表)中的第index节点中的对象, Vector 类中的 elementAt(int index) 方法返回当前向量中第 index 节点中的对象等. 有些集合的存储结构不是顺序结构, 比如 LinkedList 创建的链表
, 而有些集合的存储结构是顺序存储, 比如 ArrayList 数组表
, 因此, 链表调用 get(int index) 方法返回数据的速度比数组表调用get(int index) 方法返回数据的速度慢
, 因此当用户需要遍历集合中的对象时, 应当使用该集合提供的迭代器, 而不是让集合本身来遍历其中的对象. 由于迭代器遍历集合的方法在找到集合中的一个对象的同时, 也得到了等待遍历的后继对象的引用, 因此迭代器可以快速地遍历集合.
案例: 比较使用迭代器遍历链表 和 get(int index) 方法遍历所用时间
package com.beyond.cwq.iterator;
import java.util.Iterator;
import java.util.LinkedList;
public class TestSpeed {
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
for (int i = 0; i <= 60069; i++) {
linkedList.add("speed" + i);
}
Iterator<String> iterator = linkedList.iterator();
long startTime = System.currentTimeMillis();
while (iterator.hasNext()) {
String te = iterator.next();
}
long endTime = System.currentTimeMillis();
long result = endTime - startTime;
System.out.println("迭代器所用的时间为" + result + "毫秒");
startTime = System.currentTimeMillis();
for (int i = 0; i < linkedList.size(); i++) {
String tr = linkedList.get(i);
}
endTime = System.currentTimeMillis();
result = endTime - startTime;
System.out.println("使用get方法遍历集合所花费的时间为:" + result + "毫秒");
}
}
案例二: 使用多个集合存储对象
设计要求:
链表适合插入, 删除等操作, 但不适合查找和排序. 现在有若干个学生, 他们有姓名, 学号, 成绩 属性
- 使用链表存放学生对象
- 用一个散列表 和 一个树集存放链表中的对象
- 使用散列表查询某个学生的信息
- 通过树集将学生按成绩排序.
package com.atdhl.iteratorDemo;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;
class Student implements Comparable {
private String number, name;
private double score = 0;
private int x = 10;
public Student() {
}
public Student(String number, String name, double score) {
this.name = name;
this.number = number;
this.score = score;
}
@Override
public int compareTo(Object o) {
Student st = (Student) o;
if (Math.abs(this.score - st.score) <= 1 / 10000) {
return 1;
}
return (int) (1000 * (this.score - st.score));
}
public String getNumber() {
return number;
}
public String getName() {
return name;
}
public double getScore() {
return score;
}
}
class UseSet {
LinkedList<Student> list;
Hashtable<String, Student> table;
TreeSet<Student> tree;
public UseSet() {
list = new LinkedList<Student>();
table = new Hashtable<String, Student>();
tree = new TreeSet<Student>();
}
public void addStudent(Student stu) {
list.add(stu);
update();
}
public void lookStudent(String num) {
Student stu = table.get(num);
String number = stu.getNumber();
String name = stu.getName();
double score = stu.getScore();
System.out.println("学号:" + number + ",姓名" + name + ",分数:" + score);
}
public void printStudentByScore() {
Iterator<Student> iterator = tree.iterator();
while (iterator.hasNext()) {
Student stu = iterator.next();
String number = stu.getNumber();
String name = stu.getName();
double score = stu.getScore();
System.out.println("学号:" + number + ",姓名" + name + ",分数:" + score);
}
}
public void update() {
tree.clear();
Iterator<Student> iterator = list.iterator();
while (iterator.hasNext()) {
Student stu = iterator.next();
String number = stu.getNumber();
table.put(number, stu);
tree.add(stu);
}
}
}
public class IteratorDemo {
public static void main(String[] args) {
UseSet useSet = new UseSet();
useSet.addStudent(new Student("001", "张三", 76.89));
useSet.addStudent(new Student("002", "张四", 86.45));
useSet.addStudent(new Student("003", "张五", 56.9));
useSet.addStudent(new Student("004", "张六", 79.49));
useSet.addStudent(new Student("005", "张七", 96.89));
String n = "003";
System.out.println("查找学号为" + n + "的学生:");
useSet.lookStudent(n);
System.out.println("将学生的成绩排列:");
useSet.printStudentByScore();
}
}