LoginSignup
2
3

More than 3 years have passed since last update.

JavaのStream APIとSQLに関するメモ

Last updated at Posted at 2020-08-09

JavaのStream APIとSQLの対比に関するメモ。

Streamの公式ドキュメント

Java8の公式ドキュメントの内容を抜粋。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html

順次および並列の集約操作をサポートする要素のシーケンスです。
(中略)
コレクションとストリームは、表面上似た点があるものの、異なる目的を持っています。コレクションは主に、要素の効率的な管理やアクセスに注力しています。これに対し、ストリームは要素の直接アクセスや操作の手段を持たず、代わりにソースやそのソースに対して集約的に実行される計算操作を宣言的に記述することに注力しています。
(中略)
ストリーム・パイプラインは順次、並列のいずれかで実行できます。この実行モードは、ストリームのプロパティの1つです。ストリームの作成時には、順次実行または並列実行の初期選択が行われます。

僕の理解が足りなくてドキュメント読んでも分かりにくいですが、ざっくり書くとこんなもの。

  • コレクションと似ている
  • 集約操作を行う
  • 要素の直接アクセスや操作(get, remove)をするものではない
  • 処理を順次・並列で選択できる

集約操作はSQLをイメージしてもらえれば理解は速くなります。

Stream APIとSQLの対比一覧

Stream API 対応するSQL 説明
Stream#map SELECT Stream内の要素を別の値やオブジェクトに変換する操作
Stream#filter WHERE 条件に一致したデータのみにフィルタリングする操作。引数にはbooleanが戻り値となる式を書くことが必要。
Stream#max MAX 最大値の取得
Stream#min MIN 最小値の取得
IntStream#sum
Collectors#summingInt
SUM 合計の取得

サンプルコード

前提条件

  • lombok プラグインが導入されている前提
  • スコープは適当

人物データとクラス

人物データを格納するテーブルとそのデータを保持するクラスを以下のように定義する。

■Personテーブル

id name age job
1 yamada 25 ---:
2 suzuki 28 ---:
3 sato 30 ---:
4 nakamura 41 ---:
5 yamamoto 38 ---:
6 akiyama 22 ---:
7 tanabe 43 ---:
8 ito 24 ---:

■Personクラス

Persion.java
@Data
@AllArgsConstructor
public class Person {
    private int id;
    private String name;
    private int age;
}

更にPersonテーブルの全データを格納したリストをList<Person>として定義する。
List<Person>は以下と同義である。

List<Person> personList = Arrays.asList(
    new Person(1, "yamada", 25),
    new Person(2, "suzuki", 28),
    new Person(3, "sato", 30))
    new Person(4, "nakamura", 41))
    new Person(5, "yamamoto", 38))
    new Person(6, "akiyama", 22))
    new Person(7, "tanabe", 43))
    new Person(8, "ito", 24))
);

Stream#map

Java
List<String> nameList = personList.stream()
        .map(Person::getName)
      .collect(Collectors.toList()); 
SQL
SELECT
  p.name
FROM
  Person p

<結果>
["yamada", "suzuki", "sato", "nakamura, "yamamoto", "akiyama", "tanabe", ito]

Stream#filter

Java
List<String> nameList = personList.stream()
        .filter(p -> p.getAge() >= 40)
        .map(Person::getName)
        .collect(Collectors.toList()); 
SQL
SELECT
  p.name
FROM
  Person p
WHERE
  p.age >= 40 

<結果>
["nakamura", "tanabe"]

Stream#max

Java
Integer max = personList.stream()
        .map(Person::getAge)
        .max(Comparator.comparingInt(x -> x))
        .orElse(null);
SQL
SELECT
  max(p.age) max_age
FROM
  Person p

<結果>
43

Stream#min

Java
Integer max = personList.stream()
        .map(Person::getAge)
        .min(Comparator.comparingInt(x -> x))
        .orElse(null);
SQL
SELECT
  min(p.age) min_age
FROM
  Person p

<結果>
22

IntStream#sum/Collectors#summingInt

Java
int sum = personList.stream()
        .mapToInt(Persion::getAge)
        .sum();

int sum2 = personList.stream()
        .collect(Collectors.summingInt(Persion::getAge));
SQL
SELECT
  sum(p.age) sum_age
FROM
  Person p

<結果>
251

2
3
2

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
2
3