コース一覧
    Java中級:Streamと関数型
    collect で集める

    Java中級:Streamと関数型

    Stream APIと関数型インターフェースを学び、データ処理を宣言的で再利用しやすい形に書けるようにします。

    1
    Stream API
    01. Stream を作る5分
    02. filter で絞り込む5分
    03. map で変換する5分
    04. reduce で集約する5分
    05. collect で集める5分
    06. sorted で並び替え5分
    07. distinct で重複排除5分
    08. limit と skip5分
    09. 並列ストリーム5分
    10. Stream API まとめクイズ5分
    2
    関数型インターフェース
    01. ラムダ式の基本5分
    02. メソッド参照 ::5分
    03. Function インターフェース5分
    04. Predicate インターフェース5分
    05. Consumer と Supplier5分
    06. BiFunction と 2 引数の関数5分
    07. 関数型インターフェース まとめクイズ5分

    collect で集める

    Stream のままでは、次の行で使えない

    filter で絞り込んだ結果を、そのまま返そうとするとコンパイルが通りません。

    Java

    List<String> actives = members.stream().filter(m -> m.isActive()); // 型が合わない

    filter が返すのは Stream<String> であって List<String> ではないからです。Stream は流れている途中の状態で、そのままでは size() も呼べませんし、for で回すこともできません。流し終わったものを、使える入れ物に詰め直す必要があります。その役目が collect です。

    Java

    List<String> actives = members.stream()
        .filter(m -> m.isActive())
        .collect(Collectors.toList());

    collect は終端操作なので、ここで Stream は終わりです。toList() と書ける場面も多いですが、詰め方を細かく指定したいときは Collectors の出番になります。

    詰め方は Collectors から選ぶ

    collect の引数には「どう詰めるか」を渡します。これを毎回自分で書く必要はなく、java.util.stream.Collectors によく使うものが用意されています。

    リストではなく 1 本の文字列にまとめたいときは joining です。

    Java

    String label = names.stream()
        .collect(Collectors.joining(" / "));
    // 佐藤 / 鈴木 / 田中

    区切り文字を渡すと、要素の間にだけ挟んでくれます。末尾には付きません。要素が 1 件なら区切りは 1 つも入らず、要素が 0 件なら空文字列が返ります。自分で最後のカンマを消す処理は要りません。

    キーと値の組にしたいときは toMap です。1 つ目の式がキー、2 つ目の式が値を作ります。

    Java

    Map<String, Integer> lengthOf = names.stream()
        .collect(Collectors.toMap(n -> n, n -> n.length()));

    キーがぶつかると例外で落ちる

    toMap で気をつけたいのが、キーが重複したときです。上の例で names に同じ名前が 2 回入っていると、IllegalStateException が出て処理が止まります。

    Map にキーは 1 つしか置けないので、後から来た値で上書きするのか、先に入っていた値を残すのか、Java が勝手に決めるわけにはいきません。決め方を渡していないので、黙って片方を捨てる代わりに例外にしている、という作りです。同じキーが出うるデータを扱うときは、先に重複を落としておくか、3 つ目の引数で「ぶつかったらどちらを採るか」を渡します。

    解説

    joining は Stream<String> にしか使えません。数値の Stream から直接は呼べないので、先に文字列の Stream に変えておく必要があります。

    やってみよう

    Solution.evensJoined(int[] arr) を完成させて、配列の中の偶数だけを , 区切りでつないだ文字列を返してください。

    Arrays.stream(arr) で IntStream を作り、filter で偶数だけ残すところまでは前の回と同じです。問題はその先で、数値の Stream のままでは Collectors に渡せません。mapToObj(String::valueOf) で 1 件ずつ文字列に変えて Stream<String> にしてから、collect に Collectors.joining(",") を渡します。

    偶数が 1 つも無いときと、空配列のときは、どちらも空文字列が返ります。区切り文字の付け方も件数の判定も joining に任せられるので、自分で if を書く場面はありません。

    要件

    1. Arrays.stream(arr) で IntStream を作ること
    2. filter で偶数 (n % 2 == 0) だけ残すこと
    3. mapToObj(String::valueOf) で Stream<String> に変換してから collect(Collectors.joining(",")) で連結すること

    ヒント

    `IntStream` のままでは `Collectors.joining` を呼べないので、必ず `mapToObj` で `Stream<String>` に変換してください

    `Collectors.joining(",")` の区切り文字には半角カンマだけを渡します。スペースは入れません

    要素が 0 件のとき `Collectors.joining` は自動で空文字列を返すので、`if` で分岐する必要はありません

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

    関連レッスン

    • sorted で並び替え

      Stream の sorted() で要素を昇順に並べ替え、Collectors.joining でカンマ区切り文字列に整形するテクニックを身につけよう。

    • distinct で重複排除

      Stream の `distinct()` で配列やリストから重複要素を取り除き、ユニークな要素数を集計する書き方を身につけよう。

    • limit と skip

      Stream API の中間操作 limit と skip を使い、要素を先頭から数件だけ取り出したり、先頭の数件を飛ばしたりする方法を学んで、配列のスライス処理を Stream で書いてみよう。

    • 並列ストリーム

      Stream API の parallel() で配列を複数 CPU コアに分割集計させる並列ストリームの仕組みと、結合性・スレッド安全・順序保証など並列化の落とし穴を学びます。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • コンパイルソースをバイトコードへ変換する処理
    • 引数位置引数=順番で渡す。
    • リスト順序付きで複数の値を扱うデータ構造
    • 処理計算や代入を表す長方形
    • 配列サイズ固定の同型データの集まり
    main.java
    エディタを読み込んでいます

    メモ

    collect で集める

    ⌘S で保存