JavaのストリームAPIとは
JavaのストリームAPIは、Java8で導入されたCollection操作を簡素化し、効率的にするための機能です。
ストリームAPIにより、Collection(List、Set、Mapなど)を操作するための宣言型の方法を提供します。
ストリームAPIを使用すると、データのフィルタリング、マッピング、集計などの操作をパイプラインのチェーンのように連結して実行することができます。
主な特徴
1. 宣言型の操作:
- forループやif文を使って操作を明示的に書く必要がなく、コードが簡潔で読みやすくなります。
- 例えば、リストのフィルタリングとマッピングを以下のように書けます:
List<String> names = List.of("John", "Jane", "Jack"); List<String> upperCaseNames = names.stream() .filter(name -> name.startsWith("J")) // 先頭が「J」で始まる文字に絞り込み .map(String::toUpperCase) // 大文字に変換 .collect(Collectors.toList()); // List形式に格納
2. 中間操作と終端操作:
- 中間操作はストリームを返し、複数の操作が連結可能(例:filter、map、sorted)。
- 終端操作は最終的な結果を返す(例:collect、count、forEach)。
3. 遅延評価:
- 中間操作は遅延評価され、終端操作が呼び出された時に初めて実行されます。
これにより、パフォーマンスが最適化されます。
4. 並列処理:
- ストリームAPIは並列処理を容易に実現できます。
parallelStreamメソッドを使用すると、ストリームの操作が並列で実行され、マルチコアプロセッサを有効に活用できます。
使用例
基本的なストリーム操作
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) // 2の倍数(偶数)で絞り込み .collect(Collectors.toList()); // List形式に格納 System.out.println(evenNumbers); // [2, 4, 6]
集計操作
List<Integer> numbers = List.of(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, (a, b) -> a + b); // 順に加算 System.out.println(sum); // 15
並列処理
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.parallelStream() // 並列実行 .filter(n -> n % 2 == 0) // 2の倍数(偶数)で絞り込み .collect(Collectors.toList()); System.out.println(evenNumbers); // [2, 4, 6]
ストリームの種類
- シーケンシャルストリーム (stream()): 単一のスレッドで実行されます。
- 並列ストリーム (parallelStream()): 複数のスレッドで並列に実行されます。
まとめ
JavaのストリームAPIを活用することで、コードの可読性を向上させ、複雑なデータ操作をシンプルに記述することができます。
また、パフォーマンスの向上や並列処理の容易さも大きな利点です。
ストリームAPIで書けることは、for文で頑張ってロジックを書けば同様の処理ができます。
しかし、ソースコードの簡略化や処理パフォーマンスを考慮すると、ストリームAPIで書いた方がメリットがあることが多々あります。
複雑な要件を全てストリームAPIで無理やり書くと逆に可読性が下がりますが、Collection操作をする場合はまずはfor文よりもストリームAPIの使用を検討すると良いのではないでしょうか。