Java Iterableインターフェース/Iteratorインターフェースの実装例

#この記事を書いたきっかけ
JavaのIterableインターフェースとIteratorインターフェースって、どっちがどっちかよくわからないよね。

2つのインターフェースの違いは、
Iteratorインターフェースがイテレータを実装するためのもので、
Iterableインターフェースは拡張For文へ渡すためのもの、という役割の違いです。


#サンプルコード
クラスPrimeNumbersは整数を与えると、Iteratorを介して与えた整数以下のすべての素数を返します。

PrimeNumbersクラス

```Java:PrimeNumbers.java
import java.util.Iterator;

/**
 * 素数を計算するクラス
 */
public class PrimeNumbers implements Iterable<Integer>, Iterator<Integer> {

    /** 与えられた整数 */
    private int myNumber;
    /** 現在の算出素数 */
    private int curPrimeNumber;

    /**
     * コンストラクタ
     * @param myNumber 与えられた整数
     */
    public PrimeNumbers(int myNumber) {
        super();
        this.myNumber = myNumber;
        curPrimeNumber = 1;
    }

    /**
     * 要素のイテレータを返す。
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator<Integer> iterator() {
        // 自身のインスタンスを返す
        return this;
    }

    /**
     * 反復処理でさらに要素がある場合にtrueを返す。
     * @see java.util.Iterator#hasNext()
     */
    @Override
    public boolean hasNext() {
        // 与えられた整数が1以下なら終了
        if (myNumber <= 1)
            return false;

        // 現在の算出素数が与えられた整数に達していれば終了
        if (myNumber == curPrimeNumber)
            return false;

        int counter;
        // 前回素数の次の値から開始
        counter = curPrimeNumber + 1;

        // 開始値から順に素数であるかをチェックする
        for (int i = counter; i <= myNumber; i++) {
            int j;
            for (j = 2; j <= counter; j++) {
                // 2から順番に割っていって、割り切れれば抜ける
                if ((counter % j) == 0) {
                    break;
                }
            }
            // 割り切れる値がチェック対象の整数しかなければ素数
            if (j == counter) {
                curPrimeNumber = counter;
                return true;
            }
            counter++;
        }
        return false;
    }

    /**
     * 反復処理で次の要素を返す。
     * @see java.util.Iterator#next()
     */
    @Override
    public Integer next() {
        // 現在の算出素数を返す
        return curPrimeNumber;
    }
}
```

呼び出し方

```Java:MyClass.java
public class MyClass {
    public static void main(String... args) {
 
        // 整数を指定
        final int myNumber = 200;
        // 素数クラスを生成
        PrimeNumbers pNum = new PrimeNumbers(myNumber);
 
        // 指定整数以下の素数をすべて列挙
        for (Integer cur : pNum) {
            System.out.println(cur);
        }
    }
}
```

なお、拡張For文を使うには当該のクラスにIterable#iterator()の実装があればよく、
Iterator<E>の実装(implements)は必須ではない。
なので以下のような書き方も可能（動作は全く同じ）。

```Java:PrimeNumbers.java
import java.util.Iterator;
 
/**
 * 素数を計算するクラス
 */
public class PrimeNumbers implements Iterable<Integer> {
 
    /** 与えられた整数 */
    private int myNumber;
    /** 現在の算出素数 */
    private int curPrimeNumber;
 
    /**
     * コンストラクタ
     * @param myNumber 与えられた整数
     */
    public PrimeNumbers(int myNumber) {
        super();
        this.myNumber = myNumber;
        curPrimeNumber = 1;
    }
 
    /**
     * 要素のイテレータを返す。
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator<Integer> iterator() {
 
        // Iteratorインターフェースの実装
        Iterator<Integer> iterator = new Iterator<Integer>() {
            /**
             * 反復処理でさらに要素がある場合にtrueを返す。
             * @see java.util.Iterator#hasNext()
             */
            @Override
            public boolean hasNext() {
                // 与えられた整数が1以下なら終了
                if (myNumber <= 1)
                    return false;
 
                // 現在の算出素数が与えられた整数に達していれば終了
                if (myNumber == curPrimeNumber)
                    return false;
 
                int counter;
                // 前回素数の次の値から開始
                counter = curPrimeNumber + 1;
 
                // 開始値から順に素数であるかをチェックする
                for (int i = counter; i <= myNumber; i++) {
                    int j;
                    for (j = 2; j <= counter; j++) {
                        // 2から順番に割っていって、割り切れれば抜ける
                        if ((counter % j) == 0) {
                            break;
                        }
                    }
                    // 割り切れる値がチェック対象の整数しかなければ素数
                    if (j == counter) {
                        curPrimeNumber = counter;
                        return true;
                    }
                    counter++;
                }
                return false;
            }
 
            /**
             * 反復処理で次の要素を返す。
             * @see java.util.Iterator#next()
             */
            @Override
            public Integer next() {
                // 現在の算出素数を返す
                return curPrimeNumber;
            }
        };
 
        // イテレータを返す
        return iterator;
    }
}
```

[link-1]:http://mindalign.sblo.jp/article/183499180.html
おことわり：当記事は[ここの記事][link-1]と相互掲載です。