3
1

はじめに

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つに集約
anyMatchallMatchnoneMatch要素が条件を満たすかどうかを判定

集約

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

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1