#この記事を書いたきっかけ
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;
}
}
おことわり:当記事はここの記事と相互掲載です。