Iterator イテレータ-デザインパターン勉強メモ

Iterator(イテレータ)は日本語で「反復子」。
動詞iterateは『繰り返す』という意味。
たくさん集まっている集合に対して、1つずつアクセスする際に使うみたいです。

Java標準API

javaでは標準APIとして、これが提供されている。
java.util.Iterator

public interface java.util.Iterator {
  boolean hasNext();
  Object next();
}

メソッドhasNext()は、オブジェクト郡の中にまだアクセスしていないオブジェクトがあるかをtrueかfalseで返します。
メソッドnext()は、次のオブジェクトを返します。戻り値がObjectになっているのは、どんなオブジェクトでも良いようにです。


具体例

増補改訂版Java言語で学ぶデザインパターン入門Iteratorの章に載っているコードでは、以下のクラスとインターフェースを例に説明されています。
ソースコード増補改訂版Java言語で学ぶデザインパターン入門から誰でもダウンロードできます。

名前 解説
Aggregate 集合体を表すインターフェース
Iterator 数え上げ、スキャンを行うインターフェース
Book 本を表すクラス
BookShelf 本棚を表すクラス
BookShelfIterator 本棚をスキャンするクラス
Main 動作テスト用のクラス

本書を読み、大まかな流れを理解することはできました。
でも、手を動かして実際に弄ってみないと本当に分かっているか、分からないので、弄ってみることにしました。


・最後尾から開始して逆方向に進む。
・順方向にも逆方向にも行く(nextメソッドだけでなくpreviousメソッドも持つ)
・番号を指定して、いきなりそこにジャンプする
このようなIteratorクラスも作ることができるでしょう。p13
ちょっと作ってみます。

最後尾から開始して逆方向へ

Aggregate.java 変更なし
  1 public interface Aggregate {
  2     public abstract Iterator iterator();
  3 }
Iterator.java 変更なし
  1 public interface Iterator {
  2     public abstract boolean hasNext();
  3     public abstract Object next();
  4 }
Book.java 変更なし
  1 public class Book {
  2     private String name;
  3     public Book(String name) {
  4         this.name = name;
  5     }
  6     public String getName() {
  7         return name;
  8     }
  9 }
BookShelf.java 変更なし
  1 public class BookShelf implements Aggregate {
  2     private Book[] books;
  3     private int last = 0;
  4     public BookShelf(int maxsize) {
  5         this.books = new Book[maxsize];
  6     }
  7     public Book getBookAt(int index) {
  8         return books[index];
  9     }
 10     public void appendBook(Book book) {
 11         this.books[last] = book;
 12         last++;
 13     }
 14     public int getLength() {
 15         return last;
 16     }   
 17     public Iterator iterator() {
 18         return new BookShelfIterator(this);
 19     }   
 20 }
BookShelfIterator.java 変更あり line9とline16
  1 public class BookShelfIterator implements Iterator {
  2     private BookShelf bookShelf;
  3     private int index; 
  4     public BookShelfIterator(BookShelf bookShelf) {
  5         this.bookShelf = bookShelf;
  6         this.index = this.bookShelf.getLength();
  7     }
  8     public boolean hasNext() { 
  9         if (index > 0) {      //変更部分
 10             return true;
 11         } else {
 12             return false;
 13         }
 14     }
 15     public Object next() {
 16         index--;         //変更部分
 17         Book book = bookShelf.getBookAt(index);
 18         return book;
 19     }   
 20 }

Main.javaでテストしてみる。

  1 import java.util.*;
  2     
  3 public class Main { 
  4     public static void main(String[] args) {
  5         BookShelf bookShelf = new BookShelf(4);
  6         bookShelf.appendBook(new Book("A"));
  7         bookShelf.appendBook(new Book("B"));
  8         bookShelf.appendBook(new Book("C"));
  9         bookShelf.appendBook(new Book("D"));
 10         Iterator it = bookShelf.iterator();
 11         while (it.hasNext()) {
 12             Book book = (Book)it.next();
 13             System.out.println(book.getName());
 14         }
 15     }
 16 }
$ java Main
D
C
B
A

ヤッター。

順方向にも逆方向にも行く(nextメソッドだけでなくpreviousメソッドも持つ)

Aggregate.java 変更なし
Book.java    変更なし
BookShelf.java 変更なし

抽象メソッドpreviousを追加。

Iterator.java
  1 public interface Iterator {
  2     public abstract boolean hasNext(); 
  3     public abstract Object next();
  4     public abstract Object previous();
  5 }

抽象メソッドprebiousを実装。

BookShelfIterator.java
  1 public class BookShelfIterator implements Iterator {
  2     private BookShelf bookShelf;
  3     private int index;
  4     public BookShelfIterator(BookShelf bookShelf) {
  5         this.bookShelf = bookShelf;
  6         this.index = 0;
  7     }
  8     public boolean hasNext() {
  9         if (index < bookShelf.getLength()) {
 10             return true;
 11         } else {
 12             return false;
 13         }
 14     }
 15     public Object next() {
 16         Book book = bookShelf.getBookAt(index);
 17         index++;
 18         return book;
 19     }
 20     public Object previous() {
 21       index--;
 22       index--;
 23       Book book = bookShelf.getBookAt(index);
 24       index++;
 25       return book;
 26     }
 27 }


Main.javaで試してみる。

  1 import java.util.*;
  2 
  3 public class Main {
  4     public static void main(String[] args) {
  5         BookShelf bookShelf = new BookShelf(4);
  6         bookShelf.appendBook(new Book("A"));
  7         bookShelf.appendBook(new Book("B"));
  8         bookShelf.appendBook(new Book("C"));
  9         bookShelf.appendBook(new Book("D"));
 10         Iterator it = bookShelf.iterator();
 11         while (it.hasNext()) {
 12             Book book = (Book)it.next();
 13             System.out.println(book.getName());
 14         }
 15         Book book = (Book)it.previous();
 16         System.out.println(book.getName());
 17     }
 18 }
$ java Main
A
B
C
D
C

わーい。

学習教材

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

Javaデザインパターン徹底攻略 (標準プログラマーズライブラリ)

Javaデザインパターン徹底攻略 (標準プログラマーズライブラリ)

2008年12月23日追記

Iteratorって、よく分からなかった。でも、実装してみて、少しは分かるようになったな。