AIによる要約
Javaには通常のfor文、拡張for文、Streamなど複数の繰り返し処理があります。どれが正解かは場面によります。この記事では、初学者が迷いやすい使い分けを、現場の可読性とデバッグしやすさの観点で整理します。


Javaのコレクション処理では、同じ結果を複数の書き方で実現できます。
初学者が迷いやすいのは、for文が古くて、Streamが常に良い書き方に見えることです。
この記事のポイント
- 単純な繰り返しは拡張for文で十分なことが多い
- 抽出・変換・集計はStreamが読みやすい場合がある
- 途中に複雑な処理やデバッグが必要ならfor文が強い
- チームの読みやすさを優先して選ぶ
拡張for文は現場でも普通に使う
一覧を順番に処理するだけなら、拡張for文は今でも十分に読みやすいです。
for (Order order : orders) {
if (order.isExpired()) {
expiredOrders.add(order);
}
}
条件分岐やログ出力、途中の変数確認が必要な処理では、for文の方が追いやすいことがあります。
Streamが向いている処理
Streamは、一覧から条件に合うものを取り出す、別の形に変換する、集計する、といった処理で読みやすくなります。
List<String> activeUserNames = users.stream()
.filter(User::isActive)
.map(User::getName)
.toList();
このように、処理の流れが「絞る、取り出す、集める」と読めるならStreamは有効です。
読みにくいStreamは避ける
問題は、Streamを使うこと自体が目的になってしまうケースです。処理が長くなり、ラムダの中に条件分岐や副作用が増えると、かえって読みにくくなります。
避けたいStreamの例
- 1つのStreamチェーンが長すぎる
forEachの中で外部の変数を更新している- 例外処理やログ出力が混ざっている
- デバッグ時に中間値を追いにくい
現場での選び方
使い分けの目安
- 単純な繰り返しなら拡張for文
- 一覧の変換・抽出ならStream
- インデックスが必要なら通常のfor文
- 複雑な業務ロジックが入るなら無理にStream化しない
レビューでは「新しい書き方か」より、次に読む人が意図を追えるかが見られます。
現場ではデバッグしやすさも選定基準になる
Stream は便利ですが、現場では「短く書けるか」だけで選びません。障害調査やレビュー時に、中間値を追いやすいかも重要です。
List<Order> targetOrders = orders.stream()
.filter(order -> order.isPaid())
.filter(order -> order.isExpired())
.filter(order -> order.getAmount() >= 10000)
.toList();
この程度なら読みやすいですが、条件が業務ルールとして複雑になってくると、どの条件で落ちたのかを追いたくなります。その場合、あえて for 文にしてログやブレークポイントを置きやすくする判断もあります。
List<Order> targetOrders = new ArrayList<>();
for (Order order : orders) {
if (!order.isPaid()) {
continue;
}
if (!order.isExpired()) {
continue;
}
if (order.getAmount() < 10000) {
continue;
}
targetOrders.add(order);
}
レビューではチームの読みやすさが見られる
新人がやりがちなのは、Streamを覚えたばかりで何でもStream化することです。レビューでは、チーム全員が読めるか、既存コードの書き方と大きくズレていないかも見られます。
// レビューコメント例 // この処理は条件分岐が多く、今後ログ出力も入りそうです。 // Streamで1行に寄せるより、for文で条件ごとに分けた方が保守しやすそうです。
for文とStreamの判断基準
- 抽出・変換・集計が素直に読めるならStream
- 途中でログやデバッグが必要ならfor文
- 条件分岐が増えてきたら無理にStream化しない
- 既存コードの書き方とチームの慣れも見る
まとめ
for文とStreamは優劣ではなく使い分けです。初現場では、短さよりも読みやすさとデバッグしやすさを基準に選びましょう。