オススメ記事
【Java】Stream APIとSQLとの対比

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

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

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

JavaのStreamとは?

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

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

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

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

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

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

    Java Stream API

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

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

    サンプルコードの補足
    • lombok プラグインが導入されている前提
    • スコープは適当

      Stream#map

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

      @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"]
      

      Stream#filter

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

      @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#を比較してみてはいかが?

      3ヶ月での転職を保証する「DMM WEBCAMP」

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

      「DMM WEBCAMP」は3ヶ月でエンジニアへの転職を保証します。3ヶ月で転職できない場合は全額を返金。未経験からでも転職への自信を持ったプログラミングスクールです。

      申し込みはこちら▼

      おすすめの記事