9
10

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-07-16

この記事を書いたきっかけ

JavaのIterableインターフェースとIteratorインターフェースって、どっちがどっちかよくわからないよね。

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

サンプルコード

クラスPrimeNumbersは整数を与えると、Iteratorを介して与えた整数以下のすべての素数を返します。

PrimeNumbersクラス

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;
    }
}

呼び出し方

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の実装(implements)は必須ではない。
なので以下のような書き方も可能(動作は全く同じ)。

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;
    }
}

おことわり:当記事はここの記事と相互掲載です。

9
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10