《for文 → Stream版 書き換え練習10問(break対応・実務例付き)》
を示します。
各問題は:
- 🧠 学習ポイント
- 🏗️ for文版コード(with break)
- ⚙️ Stream版コード(書き換え)
- 📝 解説・注意点
の4段構成です。
「breakでループ終了 → StreamでfindFirst, anyMatch, limit などへ置換」を中心に扱います。
【Lv1】単純検索(最初に一致する要素)
🧠学習ポイント:break → findFirst() で置換できる。
🏗️ 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】条件を満たす要素が存在するかチェック
🧠学習ポイント:ループ内で break → anyMatch() に置換。
🏗️ 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】条件に一致する最初のオブジェクト取得
🧠学習ポイント:break → filter + 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📝解説:anyMatch が break 相当。peek は「ログ専用の副作用」に留める。
【Lv3】2段階検索(ラベル付き break 相当)
🧠学習ポイント:ラベル付き break → StreamではflatMap+findFirst。
🏗️ 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(...) | 存在確認 |
| ネスト+ラベル付きbreak | flatMap + findFirst() | 二重ループ |
| 合計が一定超えたらbreak | takeWhile() | Java 9+ |
| インデックス付きbreak | IntStream.range() | 添字操作 |
| ログ付きbreak | peek + anyMatch() | 副作用注意 |
| 入力/I/O含むbreak | forのまま推奨 | 明示的な構造が安全 |
総まとめ(習得順序)
| レベル | 習得内容 | 主なAPI |
|---|---|---|
| Lv1 | 基本検索・存在チェック | findFirst, anyMatch |
| Lv2 | 条件中断・累積条件 | takeWhile, filter |
| Lv3 | ネスト・flatMap構造 | flatMap, map |
| Lv4 | インデックス操作 | IntStream.range |
| Lv5 | ファイル・I/O応用 | Files.lines, anyMatch |
