✅ はじめに:Java 8以降の開発では「リスト操作力」が問われる
Java 8以降、Stream APIの登場によってListの操作が劇的に効率化されました。
しかし──
✅ addAllやfor文と混在してコードが読みづらくなる
✅ mapとflatMapを使い分けられない
✅ filterの順序ミスでパフォーマンス劣化
✅ null対策が甘く実行時例外が発生
✅ collectの最適な書き方がわからない
…といった悩みを抱える開発者は少なくありません。
本記事では、**「プロが実務で使うリスト処理の実践術」**を、マージ・変換・フィルタリングに焦点を当てて徹底解説します。
✅ Stream APIの基本構造
✅ Streamは元のリストを壊さない(非破壊的)
✅ 中間操作は評価されず蓄積 → 終端操作で初めて実行
✅ メソッドチェーンで可読性UP
✅ 1. リストをマージ(結合)する3つの実践パターン
❗ 従来の書き方(非推奨)
✅ ① Stream.concat()
✅ ② flatMapを使った複数リスト統合
✅ リストを動的に渡す場合にも有効
✅ 2. リストの変換(map・flatMap)実践術
✅ map(1対1変換)
✅ flatMap(1対多変換に最適)
✅ 「map + 非Stream返却」ならmap
✅ 「map + Stream返却」ならflatMap
✅ 3. フィルタリング(filter)応用パターン
✅ 基本
✅ 複数条件
✅ Optional併用(null安全)
✅ 4. プロが多用する応用操作
| 操作 | 用途 | サンプル |
|---|---|---|
| distinct | 重複削除 | .distinct() |
| sorted | 並び替え | .sorted(Comparator.comparing(User::getAge)) |
| groupingBy | グループ化 | Collectors.groupingBy(User::getDepartment) |
| collectingAndThen | 集約後処理 | .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)) |
✅ Before / Afterで理解:IDの重複を削って並べる
❌ 従来(冗長)
✅ Stream版(たった1行)
✅ 5. パフォーマンス注意点
| NG | OK | 理由 |
|---|---|---|
| filter後にmap | map後にfilter | マッピングが無駄になる |
| distinct前にmap | map後にdistinct | 重複を早く削る |
| flatMap多用 | 必要時のみ | ネストが深いと重い |
| 無闇なparallel() | データ量が少ないと逆効果 |
✅ 最後に:Stream APIは「読みやすく・壊さない」が正解
✅ 冗長なfor文はStreamで置き換え
✅ mapとflatMapは「1対1」「1対多」で使い分け
✅ filterは前処理に最適
✅ Optional併用でnull対策
✅ groupByやdistinctで実務効率化
「使える」から「読みやすい」「安全」「再現性のある」コードへ。
