プログラミング

【Java】Stream APIとSQLとの対比

java stream api

今回は、「えっ、今更?」と思われるかもしれませんが、Java8から導入されたStream APIに関する情報を掲載します。

Stream APIはラムダ式を採用していて書き方が独特ですが、慣れれば非常に使いやすくなります。書き方に迷ったときの参考にしてみてください。

随時書き足して、充実したコンテンツに仕上げていきます。

Streamとは?

まずは公式ドキュメントの内容を抜粋。

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

ドキュメントをまともに読んでも、分かりにくいことこの上ない。まあ、僕の理解が足りないだけなんですが。

で、分かったことをざっくり書くとこんなもの。

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

集約操作というのがピンときにくいのですが、基本的にはSQLをイメージしてもらえれば理解は速くなります。あとは、for文の代わりになるというあたりを理解しておきましょう。

Stream API

Stream APIは、Streamオブジェクトを作成した後、Streamクラスのメソッドの引数にラムダ式を入れて実行していくのが基本的な流れです。ラムダ式は今後バンバン使うので、理解していない人はこれを機に習得しておきましょう。

サンプルコードについては以下の条件で記述されています。

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

map

Stream#mapメソッドは、Stream内の要素を別の値やオブジェクトに変換する操作です。SQLでいえばSELECT句に該当します。

■Java

@Data
@AllArgsConstructor
class Person {
    private String name;
    private int age;    
}

class StreamExecutor {

    void execute() {
        List<Person> personList = Arrays.asList(
            new Person("yamada", 25),
            new Person("suzuki", 28), 
            new Person("sato", 30))
        );

        List<String> nameList = personList.stream()
            .map(p -> p.getName())    // .map(Person::getName) でもOK 
            .collect(Collectors.toList());

        // 結果は ["yamada", "suzuki", "sato"]
    }
}

 

■SQLに変換すると

Personテーブル

name age
yamada 25
suzuki 28
sato 30
SELECT
  p.name
FROM
  Person p

結果は ["yamada", "suzuki", "sato"]

 

filter

Stream#filterメソッドは、条件に一致したデータのみにフィルタリングする操作です。引数にははbooleanが戻り値となる式を書くことが必要です。SQLとしてはWHERE句に該当します。

■Java

@Data
@AllArgsConstructor
class Person {
    private String name;
    private int age;    
}

class StreamExecutor {

    void execute() {
        List<Person> personList = Arrays.asList(
            new Person("yamada", 25),
            new Person("suzuki", 28), 
            new Person("sato", 30))
        );

        List<String> nameList = personList.stream()
            .filter(p -> p.getAge() < 30) // 30歳未満を
            .map(p -> p.getName())
            .collect(Collectors.toList());

        // 結果は ["yamada", "suzuki"]
    }
}

 

■SQLに変換すると

Personテーブル

name age
yamada 25
suzuki 28
sato 30

 

SELECT
  p.name
FROM
  Person p
WHERE
  p.age < 30

// 結果は ["yamada", "suzuki"]

 

最後に:慣れるまでは読みにくいが、慣れたら使いやすい

JavaのStream APIについて記載しました。

この構文、慣れるまでは非常に読みづらくて理解しがたいのですが、慣れると結構さくさくと読めてきますし、使い勝手が良いなと思う場面も出てきます。今後のJavaのプログラミングにおいては、標準ともいえる機能なので、とにかく実戦で使って習得しましょう。

Stream APIは、オワコンと言われていたJavaをモダンな位置づけに戻した仕様ともいえるかなと思います。レガシー環境のJavaだけやっていると、出てこない可能性が高いです。そういう人たちは自主学習でもいいのでやってみた方が良いでしょう。

ただ、僕は以前C#をメインのスキルとして働いていたこともあり、JavaのAPIはC#のLINQの劣化版みたいな感じに思えます。言語仕様的な問題もあって、LINQの方が圧倒的に使いやすかったななんて思うこともしばしばです。

余裕のある方は、JavaとC#を比較してみてはいかが?

プログラミングスクールに通って実務までの最短距離を歩もう

人手不足により、プログラマの報酬が大きく増加しています。首都圏の場合、2~3年の経験を積めば月単価60万円(月商)も可能。

プログラマの魅力は手に職がつくこと、働く場所を選ばないことです。経験を積んでいけば、将来的には憧れのノマドワーカも夢ではありません。

ただし、プログラミングは自主学習の難易度が極めて高く、孤独で相談できない環境は多くの人が挫折します。なので、メンターや仲間と一緒に取り組めるプログラミングスクールに通うのがベターです。

中には就職支援をしてくれるスクールもあります。スクールを活用し、最短距離で実際の開発現場へ進んでいきましょう。

相談はこちらから▼