はじめに
Java 8から導入されたStream APIは、コレクションや配列などのデータの処理をより簡潔かつ関数的に記述するためのAPIです。従来のfor文を使ったループ処理と比較して、より直感的で、かつ並列処理にも対応できるという特徴があります。コレクションや配列などのデータソースに対して、宣言的な方法でデータ処理を行うことができます。ストリームAPIを使用すると、データのフィルタリング、マッピング、集計などの操作を簡潔に記述できます。
今回は、この「Java Stream APIについて」まとめてみました。
Stream APIの主な特徴
宣言型 何をしたいかを記述するだけで、具体的な処理の仕方はコンパイラが決定。
遅延評価 終端操作が実行されるまで、実際には処理が実行されない。
並列処理 並列ストリームを利用することで、マルチコアプロセッサの性能を最大限に引き出すことができる。
関数型 ラムダ式やメソッド参照を用いて、処理を関数として表現する。
Stream APIのパイプライン
Stream APIは、中間操作と終端操作を組み合わせてパイプラインを構築。
中間操作 ストリームを変換する操作。filter、mapなどが代表的。
終端操作 ストリームの処理を終了し、結果を返す操作。forEach、collectなどが代表的。
Stream APIのメリット
コードの簡潔化 for文を使ったループ処理と比較して、より少ないコードで記述できる。
可読性の向上 処理の流れが視覚的にわかりやすくなる。
並列処理 並列ストリームを利用することで、パフォーマンスを向上させることができる。
関数型プログラミングとの親和性 ラムダ式やメソッド参照を活用することで、関数型プログラミングのスタイルでコードを書くことができる。
Stream APIの利用例
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 偶数だけを抽出
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
// 全ての要素を2倍にする
List<Integer> doubledNumbers = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toList());
// 合計値を求める
int sum = numbers.stream()
.reduce(0, Integer::sum);
}
}
filter 条件に合致する要素のみを抽出。
map 各要素に対して変換を行う。
reduce 全ての要素を1つの値に集約する。
collect 結果をコレクションに格納。
ストリームの作成
ストリームは、コレクションや配列などのデータソースから作成できる。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
// リストからストリームを作成
List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> streamFromList = list.stream();
// 配列からストリームを作成
String[] array = {"apple", "banana", "cherry"};
Stream<String> streamFromArray = Arrays.stream(array);
// 値からストリームを作成
Stream<String> streamOfValues = Stream.of("apple", "banana", "cherry");
}
}
中間操作
中間操作は、ストリームを変換する操作で、遅延評価されます。中間操作は、ストリームを返すため、連鎖的に呼び出すことができる。
filter
条件に合致する要素だけを抽出
map
各要素を変換
flatMap
ネストされた構造を平坦化する
sorted
要素をソート
フィルタリング
filter
メソッドを使用して、条件に一致する要素を選択。
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream()
.filter(s -> s.startsWith("a"))
.forEach(System.out::println); // apple
マッピング
map
メソッドを使用して、要素を別の形式に変換。
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println); // APPLE, BANANA, CHERRY
ソート
sorted
メソッドを使用して、要素をソート。
List<String> list = Arrays.asList("banana", "apple", "cherry");
list.stream()
.sorted()
.forEach(System.out::println); // apple, banana, cherry
終端操作
終端操作は、ストリームの処理を実行し、結果を生成。終端操作は、ストリームを消費するため、再利用できない。
collect
結果をコレクションに収集
forEach
各要素に対して処理を実行
reduce
要素を1つに集約
anyMatch
、allMatch
、noneMatch
要素が条件を満たすかどうかを判定
集約
collect
メソッドを使用して、ストリームの要素をコレクションに集約。
import java.util.List;
import java.util.stream.Collectors;
List<String> list = Arrays.asList("apple", "banana", "cherry");
List<String> filteredList = list.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
System.out.println(filteredList); // [apple]
カウント
count
メソッドを使用して、ストリームの要素数をカウント。
List<String> list = Arrays.asList("apple", "banana", "cherry");
long count = list.stream()
.filter(s -> s.startsWith("a"))
.count();
System.out.println(count); // 1
マッチング
anyMatch
, allMatch
, noneMatch
メソッドを使用して、ストリームの要素が条件に一致するかどうかを判定。
List<String> list = Arrays.asList("apple", "banana", "cherry");
boolean anyMatch = list.stream()
.anyMatch(s -> s.startsWith("a"));
System.out.println(anyMatch); // true
リダクション
reduce
メソッドを使用して、ストリームの要素を1つの値に集約。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream()
.reduce(0, Integer::sum);
System.out.println(sum); // 15
並列ストリーム
ストリームを並列に処理することで、パフォーマンスを向上させることができる。parallelStream
メソッドを使用して並列ストリームを作成。
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.parallelStream()
.map(String::toUpperCase)
.forEach(System.out::println);
まとめ
JavaのストリームAPIは、コレクションや配列などのデータソースに対して、宣言的な方法でデータ処理を行うためのツール。中間操作と終端操作を組み合わせることで、データのフィルタリング、マッピング、ソート、集約などの操作を簡潔に記述できる。
ストリームAPIを活用することで、コードの可読性と保守性を向上させることができる。
参考文献
徹底攻略Java SE 11 Gold問題集[1Z0-816]対応
第四章 ストリームAPI
https://book.impress.co.jp/books/1121101020