Yomiage
メニュー

Java実践講座 09:ラムダとStreamで変換の流れを表す

更新 2026/9/27 6:22:11 公開

投稿者: しゅりりん

到達点は、抽出、変換、集計を分けて書くことです。前提は第07・08回です。

「どう回すか」から「何を求めるか」へ

Streamはコレクションそのものではなく、要素を処理する流れです。filterで対象を絞り、mapで形を変え、sumやtoListなどの終端操作で結果を得ます。終端操作が呼ばれるまで、中間操作は原則として実行されません。

import java.util.List;

public class Main {
    record Session(String language, int minutes) {}

    public static void main(String[] args) {
        List<Session> sessions = List.of(
            new Session("Java", 25),
            new Session("Rust", 30),
            new Session("Java", 15)
        );
        int total = sessions.stream()
            .filter(s -> s.language().equals("Java"))
            .mapToInt(Session::minutes)
            .sum();
        List<String> names = sessions.stream()
            .map(Session::language)
            .distinct()
            .sorted()
            .toList();
        System.out.println(total);
        System.out.println(names);
    }
}

Main.javaでの出力は40とJava・Rustのリストです。ラムダの s -> ... は引数から結果を作る小さな関数です。Session::minutes はminutesメソッドを呼ぶ処理を表すメソッド参照です。

流れの外側を変更しない

Stream内から共有変数へ加算するより、sumやcollectで結果を返すようにします。外部への書き込みを混ぜると、順序や実行回数に依存したバグが生まれます。peekを業務上必須の更新に使うのも避けます。

一つのStreamを終端操作後に再利用することはできません。別の計算には元のコレクションから新しくstreamを作ります。また、無理に長いチェーンへ詰め込む必要はありません。途中で複雑な分岐やエラー処理があるなら、普通のforの方が読みやすいこともあります。

parallelStreamを付ければ必ず速くなるわけではありません。要素の分割、結果の結合、共有スレッドの競合に費用がかかります。まず逐次処理で正しさを確認し、実測して選びます。

練習と解答

練習:20分以上の学習だけを対象に、合計時間を求めてください。対象が0件ならどうなりますか。

解答:sessions.stream().filter(s -> s.minutes() >= 20).mapToInt(Session::minutes).sum() で55です。空のIntStreamのsumは0です。平均を求めるaverageはOptionalDoubleを返すので、空の場合の意味を別に考えます。

公式資料

Stream APIを参照できます。


Java全20回の目次 | 前の回 | 次の回

このブラウザでは Web Speech API が利用できません。

1 / 17 · 停止中