1. 導入:なぜIterableの理解が重要なのか
Javaで開発を行う際、リストやセットなどのコレクションを操作する機会は避けられません。多くの初心者は「とりあえずfor文で回す」という書き方をしますが、java.lang.Iterableを正しく理解することで、コードの可読性が向上し、意図した通りの安全なコレクション操作が可能になります。本稿では、Javaの反復処理の仕組みと、現場で好まれる効率的な記述方法を解説します。
2. 基礎知識:IterableとIteratorの違い
Javaのコレクションフレームワークにおける「反復」には、2つの主要なインターフェースが関わっています。
・Iterableインターフェース: 「繰り返し処理ができる能力」を持つことを示すインターフェースです。これを実装しているクラス(List, Setなど)は、拡張for文が利用可能です。
・Iteratorインターフェース: 「実際に要素を一つずつ取り出すための道具」です。hasNext()で次があるか確認し、next()で要素を取得します。
つまり、Iterableは「Iteratorを生成する工場のようなもの」と考えると分かりやすいでしょう。
3. 実装/解決策:ループの種類と使い分け
Javaにおけるループ処理には主に3つの手法があります。
1. 拡張for文(for-each): 最も推奨される方法。可読性が高く、Iterableを実装している全てのクラスで使えます。
2. Iteratorによる明示的な操作: ループ中に要素を削除したい場合(removeメソッド)に必須となります。
3. Stream API(forEachメソッド): Java 8以降、より関数型に近い記述が好まれる場合に利用します。
4. サンプルプログラム
以下のコードは、Iterableを理解するための基本操作をまとめたものです。そのままコピーして動作を確認してみてください。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IterableExample {
public static void main(String[] args) {
List<String> items = new ArrayList<>();
items.add("Java");
items.add("Python");
items.add("Go");
// 1. 拡張for文(推奨:最も簡潔)
System.out.println("--- 拡張for文 ---");
for (String item : items) {
System.out.println(item);
}
// 2. Iteratorを使った明示的な操作(削除が必要な場合)
System.out.println("--- Iterator操作 ---");
Iterator<String> iterator = items.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
// 処理中に条件判定して削除する場合
if ("Python".equals(item)) {
iterator.remove();
}
}
// 3. ラムダ式を使ったforEach(Java 8以降)
System.out.println("--- forEachメソッド ---");
items.forEach(item -> System.out.println(item));
}
}
5. 応用・注意点:現場で陥りやすい罠
現場で最も注意すべきは、「拡張for文によるループ中に、元のコレクションを直接変更(追加・削除)してはいけない」という点です。これを実行すると、ConcurrentModificationExceptionという例外が発生します。
ループ中に要素を削除したい場合は、必ずIteratorのremoveメソッドを使うか、Java 8以降であればCollection.removeIfメソッドを活用してください。また、巨大なリストを扱う際は、Iteratorのオーバーヘッドも考慮しつつ、適切にアルゴリズムを選択することがシニアエンジニアとしての腕の見せ所となります。

コメント