所谓的迭代器,就是一个一个的遍历

就像下面这个图

常见的遍历语句就是for循环

for(int i = 0; i < array.length; i++){
     System.out.println(array[i]);
}

将这里的i的作用抽象化,通用化后形成的模式,就叫做Iterator模式.主要用于在数据集合中按照顺序遍历集合.Iterator模式也叫做迭代器模式.

示例程序

作用:将书(Book)放置在书架(BookShelf)上,并将书的名字按顺序显示出来

示例程序UML类图

实例程序中的所有类和接口

名字说明
Aggregate表示集合的接口
Iterator遍历集合的接口
Book表示书的实体类
BookShelf表示书架的类
BookShelfIterator遍历书架的类
Main测试程序

示例程序UML类图

1. Aggregate接口

package Iterator;

/**
 **表示集合的接口
 * @author Moti
 * @Time 2019年9月12日
 */
public interface Aggregate {
    public abstract Iterator iterator();
} 

声明的方法只有一个Iterator方法.调用Iterator方法来生成一个实现了Iterator接口的类的实例,生成用于遍历集合的迭代器.
2. Iterator接口

package Iterator;

/**
 **遍历集合的接口
 * @author Moti
 * @Time 2019年9月12日
 */
public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
} 
  • hasNext方法的返回值是波尔类型,当集合中存在下一个元素的时候返回true,否则返回false.此方法主要用于终止循环条件.
  • next方法.返回值为一个Object类型,返回集合中的一个元素,并将迭代器移动至下一个元素.

3. Book类

package Iterator;

/**
 **书类
 * @author Moti
 * @Time 2019年9月12日
 */
public class Book {
    private String name;
    public Book(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
} 

4. BookShelf类

package Iterator;

/**
 **表示书架的类
 * @author Moti
 * @Time 2019年9月12日
 */
public class BookShelf implements Aggregate {

    private Book[] books;
    private int last = 0;
    public BookShelf(int maxSize) {
        books = new Book[maxSize];
    }
    public Book getBookAt(int index) {
        return books[index];
    }
    public void appendBook(Book book) {
        this.books[last] = book;
        last++;
    }
    public int getLength() {
        return last;
    }
    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }

} 
  • BookShelf类是书架类,需要将这个类作为集合进行处理,所以要实现Aggregate接口.注意:BookShelf类还实现了Aggregate接口中的iterator方法.
  • books字段,是Book类型的数组,这个数组的大小在生成书架类实例的时候被指定,将books的可见性设置成私有,是为了防止不小心改变了该字段的值.
  • iterator方法会生产并返回一个BookShelfIterator类的实例作为书架类的迭代器,当外部想要遍历这个书架的时候就要先获得这个迭代器.

5. BookShelfIterator类

package Iterator;

/**
 * *遍历书架的类
 * @author Moti
 * @Time 2019年9月12日
 */
public class BookShelfIterator implements Iterator{

    private BookShelf bookShelf;

    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        return index < bookShelf.getLength()?true:false;
    }

    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }

} 
  • 这个类要实现迭代器的作为,所以它实现了Iterator接口.
  • bookShelf字段表示所要遍历的书架
  • index表示当前迭代器所指向的书架中书的下标,初始化的值为0
  • 生成书架迭代器的时候需要将书架作为参数传值到构造器中
  • hasNext方法是Iterator接口中声明的方法,判断是不是有下一本书,通过比较书架中书的数量和index属性
  • next方法会放回index当前所指向的书,并将index后移,相当于for循环里面的i++;

6. Main测试类

/**
 * Iterator模式(迭代器模式)
 *    一个一个的遍历
 *     主要用于在数据集合中按照顺序遍历集合
 */
package Iterator;

/**
 * *测试程序行为
 * @author Moti
 * @Time 2019年9月12日
 */
public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);
        bookShelf.appendBook(new Book("设计模式"));
        bookShelf.appendBook(new Book("Iterator模式"));
        bookShelf.appendBook(new Book("数据结构和算法"));
        bookShelf.appendBook(new Book("Spring框架源码分析"));
        Iterator iterator = bookShelf.iterator();
        while(iterator.hasNext()) {
            Book book = (Book) iterator.next();
            System.out.println(book.getName());
        }
    }
} 

通过调用书架的iterator方法获得书架的迭代器,然后进行循环获得书名.while循环的条件就是iterator.hasNext(),只要书架上面有书,循环就不会停止,之后程序会通过it.next来获取当前的图书并重新定位到下一本图书.

运行结果

迭代器在ArrayList中的应用

迭代器模式在JDK-ArrayList集合应用的源码分析

角色分析说明

  • 内部类Itr 充当具体实现迭代器Iterator 的类, 作为ArrayList 内部类
  • List 就是充当了聚合接口,含有一个iterator() 方法,返回一个迭代器对象
  • ArrayList 是实现聚合接口List 的子类,实现了iterator()
  • Iterator 接口系统提供
  • 迭代器模式解决了 不同集合(ArrayList ,LinkedList) 统一遍历问题

迭代器模式的注意事项和细节

  1. 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
  2. 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
  3. 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
  4. 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
  5. 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
最后修改日期:2020-07-13

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。