Iterable と Iterator の契約
Iterable と Iterator のインターフェース、および for-each ループが内部で動作する仕組みを理解します。
「Iterable と Iterator の契約」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
IterableとIterator
Iterable<T>とIterator<T>は、Javaのfor-eachループを支えるインターフェースです。これらを理解すると、独自のデータ構造をループで扱えるようにできます。
Iterableインターフェース
Iterable<T>には、Iterator<T>を返すiterator()という1つのメソッドがあります。Iterableを実装するクラスは、for-eachループで使用できます。
// java.lang.Iterable<T>
interface Iterable<T> {
Iterator<T> iterator();
// default: forEach, spliterator (Java 8+)
}
// Any class implementing Iterable<T> works in for-each:
class Range implements Iterable<Integer> {
private final int start, end;
Range(int start, int end) { this.start = start; this.end = end; }
public Iterator<Integer> iterator() {
return new RangeIterator(); // defined separately
}
}Iteratorインターフェース
Iterator<T>には、hasNext()、next()、そして任意実装のremove()という3つのメソッドがあります。
// java.util.Iterator<T>
interface Iterator<T> {
boolean hasNext(); // true if more elements
T next(); // returns next element, advances cursor
default void remove() { throw new UnsupportedOperationException(); }
}
// How for-each desugars internally:
// for (T item : iterable) { use(item); }
// becomes:
Iterator<T> it = iterable.iterator();
while (it.hasNext()) {
T item = it.next();
// use(item)
}For-Eachループの糖衣構文
For-eachループは、Iterable/Iteratorパターンに対する糖衣構文です。これを理解すると、カスタムIterableを正しく記述できるようになります。
List<String> names = List.of("Alice", "Bob", "Charlie");
// For-each (readable way)
for (String name : names) {
System.out.println(name);
}
// Equivalent explicit form
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String name = it.next();
System.out.println(name);
}Iteratorのカーソル状態
Iteratorはカーソル、つまりシーケンス内の位置を保持します。next()を呼び出すとカーソルが先に進みます。すべての要素を処理し終えると、iteratorをリセットすることはできません。
List<Integer> nums = List.of(1, 2, 3);
Iterator<Integer> it = nums.iterator();
System.out.println(it.hasNext()); // true
System.out.println(it.next()); // 1
System.out.println(it.next()); // 2
System.out.println(it.next()); // 3
System.out.println(it.hasNext()); // false
try {
it.next(); // NoSuchElementException
} catch (java.util.NoSuchElementException e) {
System.out.println("No more elements!");
}ConcurrentModificationException
明示的なiteratorで反復処理している途中に、Iterator.remove()以外の方法でコレクションを変更すると、ConcurrentModificationExceptionがスローされます。
List<String> list = new ArrayList<>(List.of("a", "b", "c", "d"));
// BAD: modifying collection during for-each
try {
for (String s : list) {
if ("b".equals(s)) list.remove(s); // ConcurrentModificationException!
}
} catch (java.util.ConcurrentModificationException e) {
System.out.println("Cannot modify during iteration!");
}
// GOOD: use Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("b".equals(it.next())) it.remove(); // safe
}
System.out.println(list); // [a, c, d]複数のIterator
iterator()を呼び出すたびに、新しく独立したiteratorが返されます。同じコレクションに対して、複数のiteratorを同時に使用できます。
List<Integer> nums = List.of(1, 2, 3);
Iterator<Integer> a = nums.iterator();
Iterator<Integer> b = nums.iterator();
System.out.println(a.next()); // 1
System.out.println(b.next()); // 1 (independent cursor)
System.out.println(a.next()); // 2
System.out.println(b.next()); // 2IterableとIteratorの比較
重要な違い:
- Iterable:iteratorを生成できるデータソース。複数回反復処理できます
- Iterator:シーケンス上のカーソル。1回だけ使用する状態保持型です
// Iterable: reusable
List<String> list = List.of("x", "y");
for (String s : list) {} // OK
for (String s : list) {} // OK again — new iterator each time
// Iterator: single-use
Iterator<String> it = list.iterator();
while (it.hasNext()) it.next();
// for (String s : it) {} // compile error — Iterator is not Iterable!実践:カスタムファイル行Iterable
ファイルを読み込み、その行をfor-eachループで処理できるようにIterableを実装したリーダーです。
import java.io.*;
import java.util.*;
class FileLines implements Iterable<String>, Closeable {
private final BufferedReader reader;
FileLines(String path) throws IOException {
this.reader = new BufferedReader(new FileReader(path));
}
public Iterator<String> iterator() {
return new Iterator<>() {
private String nextLine = readNext();
private String readNext() {
try { return reader.readLine(); }
catch (IOException e) { return null; }
}
public boolean hasNext() { return nextLine != null; }
public String next() {
String curr = nextLine;
nextLine = readNext();
return curr;
}
};
}
public void close() throws IOException { reader.close(); }
}forEachのデフォルトメソッド
Java 8では、IterableにデフォルトのforEach(Consumer)メソッドが追加されました。明示的なループを記述する代わりに便利に使えます。
List<String> cities = List.of("New York", "London", "Tokyo");
// for-each loop
for (String city : cities) System.out.println(city);
// forEach with lambda
cities.forEach(city -> System.out.println(city));
// forEach with method reference (most concise)
cities.forEach(System.out::println);
// For transforming: use stream
cities.stream()
.map(String::toUpperCase)
.forEach(System.out::println);実践でのIteratorパターン
Iterable/Iteratorを実装する場面のまとめ:
- カスタムデータ構造(木、グラフ、連結リスト)
- 必要に応じて要素を生成する遅延シーケンス
- リソースベースのシーケンス(ファイルの行、DBカーソル、メッセージキュー)
クイックチェック
for-eachループで反復処理している途中にコレクションを変更すると、どの例外がスローされますか。
まとめ:IterableとIteratorの契約
重要なポイント:
- Iterable
にはiterator()という1つのメソッドがあり、for-eachループをサポートできます - Iterator
にはhasNext()、next()、そして任意実装のremove()があります - For-eachループは、Iterable/Iteratorパターンに対する糖衣構文です
- iterator()を複数回呼び出すと、独立した新しいカーソルを取得できます
- for-eachの実行中はコレクションを変更せず、代わりにIterator.remove()を使用してください
- カスタムデータ構造でfor-eachループをサポートするには、Iterableを実装します
よくある質問
「Iterable と Iterator の契約」レッスンは無料ですか?
はい。「Iterable と Iterator の契約」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「Iterable と Iterator の契約」で何を学びますか?
Iterable と Iterator のインターフェース、および for-each ループが内部で動作する仕組みを理解します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「Iterable と Iterator の契約」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Iterable と Iterator の契約
- カスタム Iterator の実装
- ListIterator と双方向走査
- Fail-Fast と Fail-Safe の Iterator