JavaのStream APIの基本操作|データ処理を効率化する

先生

JavaのStream APIをマスターして、データ処理を自由自在に操ろう!🚀

Java Stream APIとは?基本概念を理解しよう

Java 8で導入されたStream APIは、コレクションなどのデータソースに対して、宣言的に一連の操作を適用し、効率的なデータ処理を可能にする強力なツールです。従来のループ処理と比較して、コードが簡潔になり、並列処理も容易になるため、パフォーマンス向上にも貢献します。

Stream APIは、データソース(コレクション、配列など)からStreamを作成し、中間操作(filter, map, sortedなど)を適用してStreamを変換し、最後に終端操作(forEach, collect, reduceなど)で結果を得るという流れで処理を行います。

Streamはデータソースを変更せず、新しいStreamを生成する点が特徴です。これにより、元のデータを安全に保ちながら、様々なデータ処理を行うことができます。

Stream APIの主要な操作:中間操作と終端操作

Stream APIの操作は大きく分けて、中間操作と終端操作の2種類があります。

中間操作: Streamを変換する操作です。複数の中間操作を連結して、パイプラインを構築できます。中間操作は、Streamを返すため、連続して呼び出すことが可能です。代表的な中間操作には、filter, map, sorted, distinct, limit, skipなどがあります。

終端操作: Streamから結果を取り出す操作です。終端操作を実行すると、Streamの処理が開始されます。終端操作は、Streamを返さないため、パイプラインの最後に記述します。代表的な終端操作には、forEach, collect, reduce, count, anyMatch, allMatch, noneMatch, findFirst, findAnyなどがあります。

以下に、中間操作と終端操作の例を示します。

List names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");

// 長さが5文字の名前をフィルタリングし、大文字に変換して出力
names.stream()
    .filter(name -> name.length() == 5)
    .map(String::toUpperCase)
    .forEach(System.out::println); // 出力: ALICE, CHARLIE

上記の例では、filtermapが中間操作、forEachが終端操作です。

Filter:条件に合致する要素を抽出

filterメソッドは、指定された条件(Predicate)を満たす要素のみを抽出します。

List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 偶数のみを抽出
List evenNumbers = numbers.stream()
    .filter(number -> number % 2 == 0)
    .collect(Collectors.toList());

System.out.println(evenNumbers); // 出力: [2, 4, 6, 8, 10]

filterメソッドに渡すPredicateは、引数を受け取りboolean値を返す関数型インタフェースです。

Map:要素を別の型に変換

mapメソッドは、Streamの各要素を指定された関数(Function)によって別の要素に変換します。

List names = Arrays.asList("Alice", "Bob", "Charlie");

// 各名前の長さを取得
List nameLengths = names.stream()
    .map(String::length)
    .collect(Collectors.toList());

System.out.println(nameLengths); // 出力: [5, 3, 7]

mapメソッドに渡すFunctionは、引数を受け取り別の型の値を返す関数型インタフェースです。

Collect:Streamの結果をコレクションに変換

collectメソッドは、Streamの処理結果をListやSetなどのコレクションに変換します。

List numbers = Arrays.asList(1, 2, 3, 4, 5);

// Streamの結果をListに変換
List numberList = numbers.stream().collect(Collectors.toList());

// Streamの結果をSetに変換
Set numberSet = numbers.stream().collect(Collectors.toSet());

System.out.println(numberList); // 出力: [1, 2, 3, 4, 5]
System.out.println(numberSet);  // 出力: [1, 2, 3, 4, 5] (順序は保証されません)

Collectorsクラスには、toList(), toSet(), toMap(), joining()など、様々な変換メソッドが用意されています。

Reduce:要素をまとめて単一の結果を生成

reduceメソッドは、Streamの要素を結合して単一の結果を生成します。例えば、数値の合計や文字列の連結などに使用できます。

List numbers = Arrays.asList(1, 2, 3, 4, 5);

// 数値の合計を計算
Optional sum = numbers.stream().reduce(Integer::sum);

System.out.println(sum.orElse(0)); // 出力: 15

reduceメソッドは、初期値を指定することも可能です。

List numbers = Arrays.asList(1, 2, 3, 4, 5);

// 数値の合計を計算 (初期値10)
int sumWithInitial = numbers.stream().reduce(10, Integer::sum);

System.out.println(sumWithInitial); // 出力: 25

初期値を指定しない場合は、Optionalで結果が返されます。これは、Streamが空の場合にnullになることを防ぐためです。

参考リンク

まとめ

Java Stream APIは、データ処理を効率化するための強力なツールです。filter, map, collect, reduceなどの基本的な操作を理解することで、より簡潔で読みやすいコードを書くことができます。ぜひStream APIを活用して、データ処理の効率化を目指してください。