1. [1, 2, 3, 4] の積は 24
  2. 要素 1 つだけの配列 [5] はそのまま 5 を返す
  3. 空配列は identity の 1 を返す
  4. [2, 3] の積は 6
  5. [1, 1, 1, 1, 1] の積は 1
  6. [2, 5, 10] の積は 100
コース一覧
Java 中級:コレクション・Stream・例外処理
reduce で集約する

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分

reduce で集約する

合計から一歩でも外れると、手が止まる

数値の Stream には sum() が用意されているので、合計を出すだけなら悩みません。困るのは、そこから少し外れたときです。全部の文字列を 1 本につなぎたい。いちばん大きい値だけ欲しい。そういう「まとめ方」に、専用のメソッドは用意されていません。

かといって for に戻ると、また入れ物の変数から書き直しです。

Java

String all = ""; for (String tag : tags) { all = all + tag; }

reduce は、この「変数を 1 つ持って、要素ごとに更新していく」形をそのままメソッドにしたものです。

Java

String all = tags.stream().reduce("", (acc, tag) -> acc + tag);

引数は「始まりの値」と「2 つを 1 つにする式」

reduce に渡すものは 2 つです。1 つ目が始まりの値、2 つ目が「2 つ受け取って 1 つ返す式」です。

上の例では、acc に「ここまでの結果」が入り、tag に「次の要素」が入ります。式が返した値が、次の呼び出しの acc になります。tags が ["a", "b", "c"] なら、"" + "a" で "a"、"a" + "b" で "ab"、"ab" + "c" で "abc" という順に育っていきます。

同じ形で、最大値も書けます。

Java

int max = IntStream.of(scores) .reduce(Integer.MIN_VALUE, (a, b) -> Math.max(a, b));

a が「ここまでの最大」、b が「次の点数」で、大きい方を返し続ければ、最後に残るのが全体の最大です。合計も積も連結も最大値も、変わるのは式の中身だけで、外側の形はどれも同じです。

始まりの値は「通しても変わらない値」を選ぶ

始まりの値は、好きな数を入れてよいわけではありません。その演算にとって「通しても結果が変わらない値」を選びます。足し算なら 0 です。0 を足しても答えは変わらないからです。文字列の連結なら空文字列です。空文字列をつないでも中身は変わりません。

ここを外すと、結果が丸ごとずれます。連結の始まりの値に "-" を入れると、先頭に余計な - が付いた文字列が返ってきます。誰もその - を足していないのに、です。

この選び方には、もう 1 つ得があります。要素が 1 つも無いとき、reduce は始まりの値をそのまま返します。「通しても変わらない値」を選んでおけば、空の Stream でも自然に正しい答えになるので、空かどうかを調べる if が要りません。

解説

どんな値を始まりに置くべきか迷ったら、要素が 1 個だけのときを考えてください。始まりの値とその 1 個を式に通して、その 1 個がそのまま返るなら正解です。

やってみよう

Solution.product(int[] arr) を完成させて、配列の全要素を掛け合わせた値を返してください。

Arrays.stream(arr) または IntStream.of(arr) で IntStream を作り、reduce に始まりの値と、2 つの数を掛ける式を渡します。for や自前の累積変数は使わないでください。

始まりの値は、掛け算にとって「通しても結果が変わらない値」を選びます。空配列を渡したときにその値がそのまま返るので、テストケースの期待値と見比べれば、選び方が合っているかどうかもすぐ分かります。

要件

  1. Arrays.stream(arr) か IntStream.of(arr) で int[] を IntStream に変換すること
  2. reduce(1, (a, b) -> a * b) のように identity に 1 を渡して畳み込むこと (空配列でも 1 が返ることを保証する)
  3. for ループや手動の累積変数を使わず、Stream API の reduce を使って書くこと

入出力例

product([1,2,3,4]) → 24 product([5]) → 5 product([]) → 1 product([2,3]) → 6 product([1,1,1,1,1]) → 1 product([2,5,10]) → 100

ヒント

`int[]` から Stream を作るには `Arrays.stream(arr)` が一番簡単です。戻り値は `IntStream` になります

`reduce` の第 1 引数 `identity` は「単位元」を渡します。掛け算の単位元は `1` なので、空配列のときの戻り値もそのまま `1` になります

`(a, b) -> a * b` はラムダ式で、Stream API が「これまでの累積 `a`」と「次の要素 `b`」を渡してくれます。返した値が次の `a` になります

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

関連レッスン

  • collect で集める

    Stream の終端操作 collect と Collectors の代表的なファクトリ (toList, toSet, toMap, joining) を学び、filter で絞り込んだ要素を joining で文字列にまとめてみよう。

  • sorted で並び替え

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

  • distinct で重複排除

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

  • limit と skip

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

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

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

  • メソッドクラスに属する関数
  • 変数データに名前をつけて参照する仕組み
  • 引数位置引数=順番で渡す。
  • 配列サイズ固定の同型データの集まり
  • テストバグを見つける工程
  • ループ繰り返し処理。矢印で戻すか専用記号で示す
  • エンドポイント「この URL を叩くとこの機能が動く」入口の住所
  • APIアプリ間でデータをやり取りする窓口
main.java
学習モード
エディタを読み込んでいます

メモ

reduce で集約する

⌘S で保存