Javaでは、コレクション(例:List、Set、Map)や配列などのデータ構造を効率的に走査するための複数の反復(イテレーション)手法が提供されています。本稿では、代表的な反復方式——拡張for文、Iteratorインターフェース、Stream API——の使い分けと実装パターンを、実践的なコード例とともに解説します。
主要な反復手法の比較
| 手法 | 使用対象 | 特徴 | 変更可能か |
|---|---|---|---|
| 拡張for文(Enhanced for-loop) | Iterableを実装するクラス(List, Setなど) | 簡潔・可読性高、内部でIteratorを使用 | 要素削除不可(ConcurrentModificationException発生) |
| Iterator明示的使用 | 同上 | remove()メソッドで安全に削除可能 | 可能(Iterator.remove()のみ) |
| Stream API(Java 8+) | Collection、配列、生成器など | 関数型スタイル、並列処理対応、中間操作と終端操作の分離 | 元のコレクションは不変(変換結果は別オブジェクト) |
実装例
1. 拡張for文による走査
最も直感的で頻繁に使われる方法です。
List<String> programmingLanguages = new ArrayList<>();
programmingLanguages.add("Kotlin");
programmingLanguages.add("Rust");
programmingLanguages.add("Go");
// 各言語名を大文字に変換して出力
for (String lang : programmingLanguages) {
System.out.println(lang.toUpperCase());
}
2. Iteratorを用いた条件付き削除
要素の動的削除が必要な場合に推奨されます。
Iterator<String> iterator = programmingLanguages.iterator();
while (iterator.hasNext()) {
String lang = iterator.next();
if (lang.length() < 4) {
iterator.remove(); // 安全な削除
}
}
// 結果: [Kotlin, Rust]
3. Stream APIによる関数型処理
フィルタリング・マッピング・集約を連鎖的に記述できます。
long countOfLongNames = programmingLanguages.stream()
.filter(lang -> lang.length() > 5)
.count();
List<String> upperCaseList = programmingLanguages.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
補足:Mapの反復
Mapはキー、値、エントリのいずれかで反復可能です。
Map<Integer, String> idToName = new HashMap<>();
idToName.put(101, "Alice");
idToName.put(102, "Bob");
// エントリ単位で走査(推奨)
idToName.entrySet().forEach(entry ->
System.out.printf("ID=%d, Name=%s%n", entry.getKey(), entry.getValue())
);