前回はReflectionを使ってクラス情報を動的に操作する方法を学びました。
今回は「Iterator(イテレータ)」と「Iterable(イテラブル)」について解説します。 これまで拡張for文でリストや配列を繰り返し処理してきましたが、その裏側でどのような仕組みが動いているのかを理解することで、自分でも繰り返し処理に対応したクラスを作れるようになります。
IteratorとIterableとは
拡張for文(for-each文)は、リストや配列の要素を順番に取り出す便利な書き方です。
List<String> names = List.of("ぱんまる", "たろう", "はなこ");
for (String name : names) {
System.out.println(name);
}
この裏側では Iterator という仕組みが使われています。Iterator は「次の要素があるか」「次の要素を取り出す」という2つの操作を提供するインターフェースです。
public interface Iterator<E> {
boolean hasNext(); // 次の要素があれば true
E next(); // 次の要素を返す
}
Iterable は「Iteratorを返せる」ことを示すインターフェースで、これを実装したクラスは拡張for文で使えるようになります。
public interface Iterable<T> {
Iterator<T> iterator(); // Iteratorを返す
}
ArrayListやHashSetなどのコレクションクラスはすべて Iterable を実装しているため、拡張for文で使えます。
サンプルコード(Iteratorの基本)
ファイル作成
「Java33」フォルダに IteratorTest.java という名前でファイルを作成します

コード入力
以下のコードを入力します。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorTest {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("ぱんまる");
names.add("たろう");
names.add("はなこ");
// 拡張for文(内部でIteratorを使っている)
System.out.println("--- 拡張for文 ---");
for (String name : names) {
System.out.println(name);
}
// Iteratorを直接使う書き方(上と同じ動作)
System.out.println("\n--- Iteratorを直接使う ---");
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
// Iteratorを使ってループ中に要素を削除する
List<String> scores = new ArrayList<>();
scores.add("apple");
scores.add("banana");
scores.add("cherry");
scores.add("apricot");
System.out.println("\n削除前: " + scores);
Iterator<String> it = scores.iterator();
while (it.hasNext()) {
String fruit = it.next();
if (fruit.startsWith("a")) {
it.remove(); // ループ中の安全な削除
}
}
System.out.println("「a」始まりを削除後: " + scores);
}
}

コンパイル
javac IteratorTest.java

実行
java IteratorTest
実行結果は次のようになります。
--- 拡張for文 ---
ぱんまる
たろう
はなこ
--- Iteratorを直接使う ---
ぱんまる
たろう
はなこ
削除前: [apple, banana, cherry, apricot]
「a」始まりを削除後: [banana, cherry]

サンプルコード(Iterableを実装して拡張for文に対応する)
自作のクラスに Iterable を実装することで、拡張for文で使えるようになります。1から指定した数まで順番に返すカウンタークラスを作ってみましょう。
ファイル作成
「Java33」フォルダに Counter.java、IterableTest.java という名前でファイルを作成します

コード入力
Counter.java に以下のコードを入力します。
import java.util.Iterator;
public class Counter implements Iterable<Integer> {
private final int max;
public Counter(int max) {
this.max = max;
}
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int current = 1;
@Override
public boolean hasNext() {
return current <= max;
}
@Override
public Integer next() {
return current++;
}
};
}
}

IterableTest.java に以下のコードを入力します。
public class IterableTest {
public static void main(String[] args) {
// 自作のCounterクラスを拡張for文で使う
Counter counter = new Counter(5);
System.out.println("--- 1から5まで ---");
for (int num : counter) {
System.out.println(num);
}
// 何度でも繰り返し使える
System.out.println("\n--- 2回目 ---");
for (int num : counter) {
System.out.print(num + " ");
}
System.out.println();
// 偶数だけ表示
System.out.println("\n--- 1から10の偶数 ---");
for (int num : new Counter(10)) {
if (num % 2 == 0) {
System.out.print(num + " ");
}
}
System.out.println();
}
}

コンパイル
javac Counter.java IterableTest.java

実行
java IterableTest
実行結果は次のようになります。
--- 1から5まで ---
1
2
3
4
5
--- 2回目 ---
1 2 3 4 5
--- 1から10の偶数 ---
2 4 6 8 10

コードの解説
Iterator<String> iterator = names.iterator() でリストのIteratorを取得し、iterator.hasNext() で次の要素があるかを確認しながら iterator.next() で要素を取り出しています。拡張for文はこの動作を自動で行っているだけで、コンパイル後には実質同じコードになります。
ループ中にリストから要素を削除したい場合、拡張for文の中で list.remove() を直接呼ぶと ConcurrentModificationException というエラーが発生します。Iteratorの it.remove() を使うことで、ループ中でも安全に要素を削除できます。
Counter クラスは Iterable<Integer> を実装し、iterator() メソッドの中で無名クラスを使って Iterator<Integer> を返しています。current 変数が1から max まで増えていき、hasNext() が false を返したらループが終わります。iterator() メソッドを呼ぶたびに新しいIteratorが作られるため、同じ Counter インスタンスを何度でも拡張for文で使えます。
まとめ
Iterator は「次の要素があるか(hasNext)」「次の要素を取り出す(next)」という2つの操作を提供し、Iterable は「Iterator を返せる(iterator)」ことを示します。拡張for文の裏側はこの仕組みで動いており、自分のクラスに Iterable を実装することで拡張for文に対応させられます。ループ中に要素を削除したい場合はIteratorの remove() を使う点も覚えておきましょう。これまで何気なく使ってきた拡張for文の仕組みを理解することで、Javaのコレクション全体への理解が一層深まります。
2026/07/24(金) ぱんまる


コメント