拡張for文
拡張for文(Enhanced For Loop)
Section titled “拡張for文(Enhanced For Loop)”拡張for文は、Java 5で導入された構文で、コレクションや配列を簡単に反復処理できる機能です。従来のfor文よりも簡潔で読みやすいコードを書けます。
実務での推奨事項:
拡張for文は、Railsのmapメソッドに相当する機能で、コレクションの各要素を反復処理する際に使用します。実務では、インデックスが不要な反復処理において、拡張for文を使用することを推奨します。コードが簡潔で読みやすく、バグが発生しにくいためです。
Railsとの対応:
# Rails (Ruby)users.map { |user| user.name }
# Java(拡張for文)for (User user : users) { System.out.println(user.getName());}なぜ拡張for文が必要なのか
Section titled “なぜ拡張for文が必要なのか”従来のfor文の問題点
Section titled “従来のfor文の問題点”問題のある実装:
// 従来のfor文での配列の反復処理int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]);}
// 問題点:// - インデックス変数(i)の管理が必要// - 配列の境界を超えるリスクがある// - コードが冗長コレクションの場合:
// 従来のfor文でのコレクションの反復処理List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (int i = 0; i < names.size(); i++) { System.out.println(names.get(i));}
// 問題点:// - インデックスベースのアクセスが必要// - Iteratorを使う方が効率的だが、コードが複雑拡張for文による解決
Section titled “拡張for文による解決”改善された実装:
// 拡張for文での配列の反復処理int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) { System.out.println(number);}
// メリット:// - インデックス変数が不要// - 配列の境界を超えるリスクがない// - コードが簡潔で読みやすいコレクションの場合:
// 拡張for文でのコレクションの反復処理List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) { System.out.println(name);}
// メリット:// - Iteratorを自動的に使用(効率的)// - コードが簡潔で読みやすい// - 型安全性が保証される拡張for文の基本構文
Section titled “拡張for文の基本構文”for (要素の型 変数名 : コレクションまたは配列) { // 処理}構文の説明:
- 要素の型: コレクションや配列の要素の型
- 変数名: 各要素を格納する変数名
- コレクションまたは配列: 反復処理する対象
配列での使用例
Section titled “配列での使用例”// int配列の反復処理int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) { System.out.println(number);}// 出力:// 1// 2// 3// 4// 5// String配列の反復処理String[] fruits = {"Apple", "Banana", "Orange"};
for (String fruit : fruits) { System.out.println(fruit);}// 出力:// Apple// Banana// Orangeコレクションでの使用例
Section titled “コレクションでの使用例”// Listの反復処理List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) { System.out.println(name);}// 出力:// Alice// Bob// Charlie// Setの反復処理Set<Integer> numbers = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer number : numbers) { System.out.println(number);}// 注意: Setは順序が保証されないため、出力順序は不定// Mapの反復処理(エントリセットを使用)Map<String, Integer> scores = new HashMap<>();scores.put("Alice", 85);scores.put("Bob", 92);scores.put("Charlie", 78);
for (Map.Entry<String, Integer> entry : scores.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue());}// 出力:// Alice: 85// Bob: 92// Charlie: 78拡張for文の実践例
Section titled “拡張for文の実践例”1. 条件に合う要素の処理
Section titled “1. 条件に合う要素の処理”// 偶数のみを処理List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (Integer number : numbers) { if (number % 2 == 0) { System.out.println(number + " is even"); }}// 出力:// 2 is even// 4 is even// 6 is even// 8 is even// 10 is even2. 要素の変換と集約
Section titled “2. 要素の変換と集約”// 文字列の長さの合計を計算List<String> words = Arrays.asList("Hello", "World", "Java");
int totalLength = 0;for (String word : words) { totalLength += word.length();}
System.out.println("Total length: " + totalLength);// 出力: Total length: 143. オブジェクトのプロパティへのアクセス
Section titled “3. オブジェクトのプロパティへのアクセス”// Userクラスの定義class User { private String name; private int age;
public User(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }}
// Userオブジェクトのリストを処理List<User> users = Arrays.asList( new User("Alice", 25), new User("Bob", 30), new User("Charlie", 22));
for (User user : users) { System.out.println(user.getName() + " is " + user.getAge() + " years old");}// 出力:// Alice is 25 years old// Bob is 30 years old// Charlie is 22 years old4. ネストしたコレクションの処理
Section titled “4. ネストしたコレクションの処理”// リストのリストを処理List<List<Integer>> matrix = Arrays.asList( Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));
for (List<Integer> row : matrix) { for (Integer value : row) { System.out.print(value + " "); } System.out.println();}// 出力:// 1 2 3// 4 5 6// 7 8 9拡張for文の制限事項
Section titled “拡張for文の制限事項”1. インデックスにアクセスできない
Section titled “1. インデックスにアクセスできない”問題のある実装:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 拡張for文ではインデックスにアクセスできないfor (String name : names) { // インデックスが必要な場合は使用できない // System.out.println(i + ": " + name); // エラー}解決方法:
// インデックスが必要な場合は、従来のfor文を使用List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (int i = 0; i < names.size(); i++) { System.out.println(i + ": " + names.get(i));}// 出力:// 0: Alice// 1: Bob// 2: Charlie2. 要素の変更ができない
Section titled “2. 要素の変更ができない”問題のある実装:
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
// 拡張for文では要素を変更できないfor (Integer number : numbers) { number = number * 2; // これは元のリストを変更しない}
System.out.println(numbers);// 出力: [1, 2, 3, 4, 5](変更されていない)解決方法:
// 要素を変更する場合は、従来のfor文を使用List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (int i = 0; i < numbers.size(); i++) { numbers.set(i, numbers.get(i) * 2);}
System.out.println(numbers);// 出力: [2, 4, 6, 8, 10]3. 逆順の反復処理ができない
Section titled “3. 逆順の反復処理ができない”問題のある実装:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 拡張for文では逆順の反復処理ができない// 逆順にするには、従来のfor文を使用for (int i = names.size() - 1; i >= 0; i--) { System.out.println(names.get(i));}// 出力:// Charlie// Bob// Alice4. 早期終了(break)は可能
Section titled “4. 早期終了(break)は可能”// 拡張for文でもbreakは使用可能List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
for (String name : names) { if (name.equals("Charlie")) { break; // ループを終了 } System.out.println(name);}// 出力:// Alice// Bob5. スキップ(continue)も可能
Section titled “5. スキップ(continue)も可能”// 拡張for文でもcontinueは使用可能List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
for (Integer number : numbers) { if (number % 2 == 0) { continue; // 次の反復に進む } System.out.println(number);}// 出力:// 1// 3// 5拡張for文と従来のfor文の使い分け
Section titled “拡張for文と従来のfor文の使い分け”拡張for文を使うべき場合
Section titled “拡張for文を使うべき場合”-
シンプルな反復処理
// 各要素を処理するだけfor (String name : names) {System.out.println(name);} -
インデックスが不要な場合
// インデックスを使わない処理for (User user : users) {processUser(user);} -
読みやすさを重視する場合
// コードが簡潔で読みやすいfor (Product product : products) {if (product.isAvailable()) {addToCart(product);}}
従来のfor文を使うべき場合
Section titled “従来のfor文を使うべき場合”-
インデックスが必要な場合
// インデックスを使う処理for (int i = 0; i < array.length; i++) {System.out.println(i + ": " + array[i]);} -
要素を変更する場合
// 要素を変更する処理for (int i = 0; i < list.size(); i++) {list.set(i, list.get(i) * 2);} -
逆順の反復処理が必要な場合
// 逆順の反復処理for (int i = list.size() - 1; i >= 0; i--) {System.out.println(list.get(i));}
拡張for文の内部動作
Section titled “拡張for文の内部動作”Iteratorパターンの使用
Section titled “Iteratorパターンの使用”拡張for文は、内部的にIteratorパターンを使用しています。
// 拡張for文List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) { System.out.println(name);}
// これは以下のコードと同等Iterator<String> iterator = names.iterator();while (iterator.hasNext()) { String name = iterator.next(); System.out.println(name);}メリット:
- 効率的: Iteratorを使用することで、コレクションの種類に関わらず効率的に処理できる
- 型安全: コンパイル時に型チェックが行われる
- 簡潔: コードが簡潔で読みやすい
拡張for文のポイント:
- 基本構文:
for (要素の型 変数名 : コレクションまたは配列) - メリット: インデックス変数が不要、コードが簡潔、型安全
- 制限事項: インデックスにアクセスできない、要素を変更できない、逆順の反復処理ができない
- 使い分け: シンプルな反復処理には拡張for文、インデックスや要素の変更が必要な場合は従来のfor文
- 内部動作: Iteratorパターンを使用して効率的に処理
適切に拡張for文を使用することで、コードを簡潔で読みやすく、保守しやすくできます。