1. 1〜6 の中から偶数だけを , で連結する
  2. 奇数しかない場合は空文字列を返す
  3. 空配列なら空文字列を返す
  4. 偶数が 1 つだけなら delimiter なしでそのまま返る
  5. 負の偶数も含める
コース一覧
Java 中級:コレクション・Stream・例外処理
collect で集める

Java 中級:コレクション・Stream・例外処理

コレクション、ジェネリクス、例外処理、Stream API、関数型インターフェース、日付処理、ファイル I/O、継承など Java の中級トピックを実践的に学べるコースです。Java の基礎文法とオブジェクト指向を理解している学習者を対象に、現場の Java コードを読み書きするための知識を補強します。約 16 時間 (1 日 30 分 × 32 日) で 64 レッスンを修了でき、修了後は Spring Boot や業務システム開発に必要な Java 力が身につきます。

1
コレクション基礎
01. ArrayList を使う5分
02. List を走査する5分
03. 要素の削除と検索5分
04. HashMap の基本5分
05. Map を走査する5分
06. Set で重複を排除5分
07. Collections クラスの便利メソッド5分
08. コレクション基礎 まとめクイズ5分
2
ジェネリクス
01. ジェネリッククラスを作る5分
02. ジェネリックメソッド5分
03. 境界型パラメータ5分
04. ワイルドカード ?5分
05. Pair<K,V> を作る5分
06. ジェネリクス まとめクイズ5分
3
例外処理
01. try-catch で例外をつかむ5分
02. 複数の catch ブロック5分
03. throws と例外の伝播5分
04. 独自の例外を作る5分
05. try-with-resources5分
06. finally ブロック5分
07. 例外処理 まとめクイズ5分
4
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分
5
関数型インターフェース
01. ラムダ式の基本5分
02. メソッド参照 ::5分
03. Function インターフェース5分
04. Predicate インターフェース5分
05. Consumer と Supplier5分
06. BiFunction と 2 引数の関数5分
07. 関数型インターフェース まとめクイズ5分
6
文字列操作
01. String.format で書式化5分
02. StringBuilder で連結5分
03. 正規表現の基本5分
04. split と join5分
05. 文字列操作 まとめクイズ5分
7
日付と時刻
01. LocalDate で日付を扱う5分
02. LocalDateTime で時刻も扱う5分
03. Duration で時間差を計算5分
04. 日付の書式化とパース5分
05. 日付の加減算5分
06. 日付と時刻 まとめクイズ5分
8
ファイル I/O
01. Files でファイルに書き込む5分
02. ファイルを行単位で読む5分
03. Path でファイルパスを扱う5分
04. BufferedReader と Stream API5分
05. ファイルの存在確認と削除5分
06. ファイル I/O まとめクイズ5分
9
継承とポリモーフィズム
01. extends で継承する5分
02. super で親を呼ぶ5分
03. メソッドのオーバーライド5分
04. abstract で抽象クラス5分
05. interface で契約を定義5分
06. default メソッド5分
07. instanceof と型パターン5分
08. ポリモーフィズムを活かす5分
09. 継承とポリモーフィズム まとめクイズ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(",")) で連結すること

入出力例

evensJoined([1,2,3,4,5,6]) → "2,4,6" evensJoined([1,3,5]) → "" evensJoined([]) → "" evensJoined([2]) → "2" evensJoined([-4,-3,-2,-1,0]) → "-4,-2,0"

ヒント

`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 で保存