Java | for文 → Stream版 書き換え練習10問

Java Java
スポンサーリンク

《for文 → Stream版 書き換え練習10問(break対応・実務例付き)》
を示します。
各問題は:

  • 🧠 学習ポイント
  • 🏗️ for文版コード(with break)
  • ⚙️ Stream版コード(書き換え)
  • 📝 解説・注意点

の4段構成です。
「breakでループ終了 → StreamでfindFirst, anyMatch, limit などへ置換」を中心に扱います。


【Lv1】単純検索(最初に一致する要素)

🧠学習ポイントbreakfindFirst() で置換できる。

🏗️ for文版

List<String> users = List.of("Alice", "Bob", "Charlie", "David");
for (String name : users) {
    if (name.equals("Charlie")) {
        System.out.println("見つけた: " + name);
        break;
    }
}
Java

⚙️ Stream版

users.stream()
     .filter(name -> name.equals("Charlie"))
     .findFirst()
     .ifPresent(name -> System.out.println("見つけた: " + name));
Java

📝解説
findFirst() は「最初に条件を満たした要素」で処理を止める。break 相当。


【Lv1】条件を満たす要素が存在するかチェック

🧠学習ポイント:ループ内で breakanyMatch() に置換。

🏗️ for文版

boolean found = false;
for (String s : List.of("A", "B", "C")) {
    if (s.equals("B")) {
        found = true;
        break;
    }
}
System.out.println(found);
Java

⚙️ Stream版

boolean found = List.of("A", "B", "C")
                    .stream()
                    .anyMatch(s -> s.equals("B"));
System.out.println(found);
Java

📝解説
anyMatch は条件を満たした時点で評価を止める。ループ+breakと同等の早期終了。


【Lv2】条件に一致する最初のオブジェクト取得

🧠学習ポイントbreakfilter + findFirst()

🏗️ for文版

User result = null;
for (User u : users) {
    if (u.getAge() >= 30) {
        result = u;
        break;
    }
}
Java

⚙️ Stream版

User result = users.stream()
                   .filter(u -> u.getAge() >= 30)
                   .findFirst()
                   .orElse(null);
Java

📝解説
orElse(null) で「見つからなかった場合」に null を返す。


【Lv2】合計が一定値を超えたら中断

🧠学習ポイント:Stream では takeWhile()(Java 9+)で break 相当が可能。

🏗️ for文版

int sum = 0;
for (int n : numbers) {
    sum += n;
    if (sum > 50) {
        break;
    }
}
System.out.println(sum);
Java

⚙️ Stream版

int sum = numbers.stream()
                 .takeWhile(n -> n <= 50) // 50を超えたらストップ
                 .mapToInt(Integer::intValue)
                 .sum();
System.out.println(sum);
Java

📝解説
takeWhile は条件を満たす間だけ処理。break のような早期終了ができる。


【Lv3】不正データ検出(ログ出力して中断)

🧠学習ポイント:Streamではpeek()でログ、副作用注意。

🏗️ for文版

for (Record r : records) {
    if (!r.isValid()) {
        logger.error("不正データ: " + r.getId());
        break;
    }
    process(r);
}
Java

⚙️ Stream版

boolean hasInvalid = records.stream()
    .peek(r -> { if (!r.isValid()) logger.error("不正データ: " + r.getId()); })
    .anyMatch(r -> !r.isValid());

if (!hasInvalid) {
    records.forEach(this::process);
}
Java

📝解説
anyMatchbreak 相当。peek は「ログ専用の副作用」に留める。


【Lv3】2段階検索(ラベル付き break 相当)

🧠学習ポイント:ラベル付き break → StreamではflatMapfindFirst

🏗️ for文版

Outer:
for (List<Item> list : itemGroups) {
    for (Item item : list) {
        if (item.isTarget()) {
            System.out.println(item);
            break Outer;
        }
    }
}
Java

⚙️ Stream版

itemGroups.stream()
    .flatMap(List::stream)
    .filter(Item::isTarget)
    .findFirst()
    .ifPresent(System.out::println);
Java

📝解説
複数リストを結合して flatMap。これで二重ループ+breakに相当。


【Lv3】複数条件で break

🧠学習ポイント:複雑な条件も filter でシンプルに。

🏗️ for文版

for (Order o : orders) {
    if (o.isCancelled() || o.getPrice() < 0) {
        break;
    }
}
Java

⚙️ Stream版

boolean invalid = orders.stream()
                        .anyMatch(o -> o.isCancelled() || o.getPrice() < 0);
Java

📝解説
複雑な if 条件を 1行で表現。anyMatch は早期終了する。


【Lv4】リトライ処理(Stream非推奨例)

🧠学習ポイント:副作用を伴うループはStreamに向かない。

🏗️ for文版

for (int i = 1; i <= 3; i++) {
    if (tryCall()) {
        break;
    }
}
Java

⚙️ Stream版(非推奨)

IntStream.rangeClosed(1, 3)
         .anyMatch(i -> tryCall());
Java

📝解説
動作はするが「副作用的」。読みづらくなる。
👉 実務では for版を推奨。


【Lv4】最初の一致とインデックス取得

🧠学習ポイントbreakでindexを得る → StreamではIntStream.rangeで再現。

🏗️ for文版

int index = -1;
for (int i = 0; i < list.size(); i++) {
    if (list.get(i).equals("target")) {
        index = i;
        break;
    }
}
System.out.println(index);
Java

⚙️ Stream版

int index = IntStream.range(0, list.size())
                     .filter(i -> list.get(i).equals("target"))
                     .findFirst()
                     .orElse(-1);
System.out.println(index);
Java

📝解説
IntStream.range で添字を扱える。findFirst が break。


【Lv5】ファイル中断処理(I/O 早期終了)

🧠学習ポイント:for+break → Streamの短絡終端操作。

🏗️ for文版

for (String line : Files.readAllLines(Path.of("data.txt"))) {
    if (line.contains("ERROR")) {
        System.out.println("エラー行検出");
        break;
    }
}
Java

⚙️ Stream版

try (Stream<String> lines = Files.lines(Path.of("data.txt"))) {
    lines.anyMatch(line -> {
        if (line.contains("ERROR")) {
            System.out.println("エラー行検出");
            return true;
        }
        return false;
    });
}
Java

📝解説
anyMatch は「trueを返したら即中断」=breakと同等。I/Oにも有効。


まとめ表(早見変換)

for文構文Stream構文備考
if (...) break;findFirst() / anyMatch()早期終了
flag = true; break;.anyMatch(...)存在確認
ネスト+ラベル付きbreakflatMap + findFirst()二重ループ
合計が一定超えたらbreaktakeWhile()Java 9+
インデックス付きbreakIntStream.range()添字操作
ログ付きbreakpeek + anyMatch()副作用注意
入力/I/O含むbreakforのまま推奨明示的な構造が安全

総まとめ(習得順序)

レベル習得内容主なAPI
Lv1基本検索・存在チェックfindFirst, anyMatch
Lv2条件中断・累積条件takeWhile, filter
Lv3ネスト・flatMap構造flatMap, map
Lv4インデックス操作IntStream.range
Lv5ファイル・I/O応用Files.lines, anyMatch

Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました