如果要问java中使用最多的一种模式,答案不是单例模式,也不是工厂模式,更不是策略模式,而是迭代器模式,先来看一段代码吧:
public static void print(Collection coll){
Iterator it = coll.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
这个方法的作用是循环打印一个字符串集合,里面就用到了迭代器模式,java语言已经完整地实现了迭代器模式,Iterator翻译成汉语就是迭代器的意思。提到迭代器,首先它是与集合相关的,集合也叫聚集、容器等,我们可以将集合看成是一个可以包容对象的容器,例如List,Set,Map,甚至数组都可以叫做集合,而迭代器的作用就是把容器中的对象一个一个地遍历出来。
基本介绍
原理类图
抽象容器(Aggregate):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
具体的聚集类(ConcerateAggregate):实现createIterator()方法返回具体的一个迭代器
具体迭代器(ConcreteIterator):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
抽象迭代器(Iterator):定义遍历元素所需要的方法,一般来说会有这么几个方法:取得第一个元素的方法first(),取得下一个元素的方法next(),判断是否遍历结束的方法hasNext()),移出当前对象的方法remove()。
下面我们用一个专业管理的例子来实现迭代器模式的演示:
public class Major {
private String name;//专业名称
private String desc;//专业描述
public Major(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Project{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
抽象迭代器(Iterator)
public interface MajorIterator {
boolean hasNext();
Major next();
}
具体迭代器(ConcreteIterator):
public class MajorIteratorImpl implements MajorIterator{
private List<Major> list;
private int index=0;
public MajorIteratorImpl(List<Major> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return index<list.size();
}
@Override
public Major next() {
Major major=list.get(index);
index++;
return major;
}
}
抽象容器(Aggregate):
public interface majorAggregate {
void addMajor(Major major);
void removeMajor(Major major);
MajorIterator getMajorIterator();
}
具体的聚集类(ConcerateAggregate)
public class majorAggregateImpl implements majorAggregate{
private List<Major> list;
public majorAggregateImpl() {
}
public majorAggregateImpl(List<Major> list) {
this.list = list;
}
@Override
public void addMajor(Major major) {
this.list.add(major);
}
@Override
public void removeMajor(Major major) {
this.list.remove(major);
}
@Override
public MajorIterator getMajorIterator() {
return new MajorIteratorImpl(list);
}
}
clent
public class Test {
public static void main(String[] args) {
majorAggregate majorAggregate=new majorAggregateImpl(new ArrayList<>());
majorAggregate.addMajor(new Major("软件工程","软件工程专业"));
majorAggregate.addMajor(new Major("计算机科学与技术","计算机科学与技术专业"));
majorAggregate.addMajor(new Major("网络工程","网络工程"));
MajorIterator majorIterator=majorAggregate.getMajorIterator();
while (majorIterator.hasNext()){
System.out.println(majorIterator.next());
}
}
}
Project{
name='软件工程', desc='软件工程专业'}
Project{
name='计算机科学与技术', desc='计算机科学与技术专业'}
Project{
name='网络工程', desc='网络工程'}
我们平时使用ArrayList
public class Test {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("abc");
list.add("def");
list.add("xyz");
list.add("jkl");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
下面我们来看源码:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
transient Object[] elementData; // non-private to simplify nested class access
private int size;
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public ListIterator<E> listIterator() {
return new ListItr(0);
}
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
public E next() {
//...
}
public E next() {
//...
}
public void remove() {
//...
}
//...
}
private class ListItr extends Itr implements ListIterator<E> {
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public E previous() {
//...
}
public void set(E e) {
//...
}
public void add(E e) {
//...
}
//...
}
从 ArrayList 源码中看到了有两个迭代器 Itr 和 ListItr,分别实现 Iterator 和 ListIterator 接口;
先看 ListIterator 源码
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
E next();
boolean hasPrevious(); // 返回该迭代器关联的集合是否还有上一个元素
E previous(); // 返回该迭代器的上一个元素
int nextIndex(); // 返回列表中ListIterator所需位置后面元素的索引
int previousIndex(); // 返回列表中ListIterator所需位置前面元素的索引
void remove();
void set(E var1); // 从列表中将next()或previous()返回的最后一个元素更改为指定元素e
void add(E var1);
}
接着是 Iterator 的源码
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 备注:JAVA8允许接口方法定义默认实现
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
通过源码我们看出:ListIterator 是一个功能更加强大的迭代器,它继承于 Iterator 接口,只能用于各种List类型的访问。可以通过调用 listIterator() 方法产生一个指向List开始处的 ListIterator, 还可以调用 listIterator(n) 方法创建一个一开始就指向列表索引为n的元素处的 ListIterator。
Iterator 和 ListIterator 主要区别概括如下:
ListIterator 有 add() 方法,可以向List中添加对象,而 Iterator 不能
ListIterator 和 Iterator 都有 hasNext() 和 next() 方法,可以实现顺序向后遍历,但是 ListIterator 有 hasPrevious() 和 previous() 方法,可以实现逆向(顺序向前)遍历。Iterator 就不可以。
ListIterator 可以定位当前的索引位置,nextIndex() 和 previousIndex() 可以实现。Iterator 没有此功能。
都可实现删除对象,但是 ListIterator 可以实现对象的修改,set() 方法可以实现。Iierator 仅能遍历,不能修改。
优点:
缺点:
适用场景: