【Java学習|豆知識】Java Stream APIを極める!静的ファクトリメソッド完全ガイド

1. 導入:なぜStreamの生成方法を知る必要があるのか

JavaのStream APIは、単にコレクションを処理するだけでなく、ゼロからデータを生成したり、複数のストリームを結合したりと、極めて柔軟なデータフローを構築できます。しかし、多くの開発者は「Listからのstream()」しか使っていません。Streamの生成テクニックを習得することで、一時的な変数を減らし、より宣言的で読みやすいコードを書くことが可能になります。

2. 基礎知識:Streamの静的ファクトリメソッドとは

Streamインターフェースには、コレクションを介さずにストリームを生成したり、既存のストリームを操作したりするための静的メソッドが用意されています。これらを活用することで、テスト用のダミーデータ生成や、複雑な条件分岐の排除が容易になります。

3. 実装と解決策:各メソッドの役割

それぞれのメソッドには明確な役割があります。

Stream.of(): 指定した複数の要素からストリームを作成します。
Stream.ofNullable(): 引数がnullなら空のストリームを、そうでなければ要素を含むストリームを返します。NullPointerExceptionを避ける際に非常に有用です。
Stream.concat(): 2つのストリームを連結します。
Stream.empty(): 要素を持たない空のストリームを生成します。
Stream.iterate(): 初期値から順次計算(インクリメントなど)して無限ストリームを生成します。
Stream.generate(): Supplierを用いて定数や乱数を無限に生成します。

4. サンプルプログラム

以下は、これらの機能を組み合わせた実用的なサンプルです。

import java.util.stream.Stream;
import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        // 1. of() で直接要素を指定
        Stream<String> s1 = Stream.of("Java", "Kotlin");

        // 2. ofNullable() でnull安全に処理
        String nullableStr = null;
        Stream<String> s2 = Stream.ofNullable(nullableStr); // nullでも例外にならず空になる

        // 3. concat() で連結
        Stream<String> combined = Stream.concat(s1, s2);

        // 4. iterate() で連番生成(limitで打ち切るのが基本)
        Stream<Integer> numbers = Stream.iterate(1, n -> n + 1).limit(5);

        // 5. generate() で乱数生成
        Stream<Double> randoms = Stream.generate(Math::random).limit(3);

        // 結果の出力
        combined.forEach(System.out::println);
        numbers.forEach(n -> System.out.print(n + " "));
    }
}

5. 応用・注意点:現場で陥りやすい罠

実務で特に注意すべき点は以下の2点です。

無限ストリームの扱い: iterate()やgenerate()は「無限」ストリームです。必ず .limit() や .takeWhile() を使用して、どこかで処理を終了させるようにしてください。これらを忘れると、メモリ不足や無限ループの原因となります。
ストリームの再利用: Streamは「一度きりの使い捨て」です。一度終端操作(forEachやcollectなど)を行うと、そのストリームは閉じられます。同じデータを再度利用したい場合は、Stream自体ではなく、Supplier<Stream<T>>として定義して、呼び出しのたびに新しいストリームを生成する設計にするのがシニアエンジニアの定石です。

これらのメソッドを使いこなすことで、コレクションの操作がより洗練されたものになるはずです。ぜひ日々の開発に取り入れてみてください。

コメント

タイトルとURLをコピーしました