mmts1007’s diary

プログラミング関連の技術系ブログです。

Java Stream API

前回の記事に引き続き Java に関して。

この記事読んでくださった前提で記事を書きます。 mmts1007.hatenablog.jp

Java Stream API

コレクション(List, Map 等) に対する要素の関数型の操作をサポートするクラスです
関数型というのが、ラムダ式のことだと思ってください。

Stream とは

Stream は大きく 3 つの操作から成り立っています。
具体的にはソース中間操作終端操作です。

ソース

コレクション(List, Map) からストリームを生成するための処理です。

中間操作

ストリームの要素を加工、変換、ソートするための処理です。

終端操作

ストリームを完了させるための処理です。 例として、ストリームの要素を集約、カウントします。

サンプルソース

gist6c1daf62d8fd167ae98c

代表的なメソッド

ソース

  • stream コレクション(List, Map) からストリームを生成するためのメソッドです。

中間操作

  • map mapping の略(おそらく)で、ラムダ式で指定された処理方法で要素の型変換を行ったストリームを返却します。 私は A クラスから B クラスにマッピングすると覚えています。

  • filter ラムダ式で指定した条件が true になるオブジェクトのみ抽出したストリームを返却します。

  • distinct 重複を除いたストリームを返却します。

  • sorted ソートを行ったストリームを返却します。

終端操作

  • forEach コレクションの各要素に対してラムダ式で指定した処理を行う場合に使用します。

  • count ストリームの要素の個数をカウントします。

  • collect ラムダ式に指定した方法でストリームの要素を集約します。

ラムダ式 x Stream API

すでにお分りかもしれませんが、 Stream APIにはラムダ式が必須になります。

例えば filter メソッドはフィルタリングの条件を渡すだけで、フィルタリングを行ってくれます。 開発者はフィルタリングの方法を全て実装する必要は無くなります。条件の実装に集中して行えば良いのです。 ラムダ式は Stream API のような場合に強力な力を発揮します。

Stream API の利点

直感的なコーディング

サンプルソースの最後に記載しましたが、
Stream API は日本語的に流れるように記述することができ、とても直感的です。

例えば、 従業員リストから 年齢が 30 歳以下でかつ、住所が東京なデータを取得する 場合は

employeeList.stream()
    .filter(employee -> employee.age <= 30)  // 年齢が 30 歳以下で
    .filter(employee -> employee.address == "東京") // 住所が "東京"
    .forEach(System.out::println);

と日本語をそのままメソッドマッピングしたように記述することができます。

並列処理が容易

Stream API は内部イテレータのため、並列処理を容易に行えます。 並列処理を行う場合は、ストリームに対して parallel メソッドを使用することで並列に処理することができます。

今回はここまで。

Java のラムダ式

何書くか悩みましたが、今回は Java 8 で導入されたラムダ式について

今更!? って思われるかもしれませんが、
私自身理解するのに苦労したので、まとめるという意味で書きます。

ラムダ式とは

ラムダ式をとっても簡単に説明すると
メソッドの引数に処理を渡すための構文だと思ってください。

ラムダ式のサンプル

gista37e6fba2aafde4cf230

ラムダ式で書かれている部分は下記のとおりです https://gist.github.com/mmts1007/a37e6fba2aafde4cf230#file-hellolambda-java-L17-L19

さらにフォーマットを修正すると下記のとおりです。

(String name) -> { System.out.println(name); }

ラムダ式は下記のように記述をします。

( 処理に渡す引数 ) -> { 処理内容 }

これより names.stream().forEach((String name) -> { System.out.println(name); }); ) の処理は
forEach によって得られた 1 つの要素を name という変数として定義し、処理内容 ( System.out.println ) に渡す
ということを行っています。
よって names の各要素が 1 つずつ標準出力に出力されます。

利用場面

今はラムダ式のメリットが分かりにくいと思いますが、
次の記事に書く Stream API について触れれば、
ラムダ式のメリットが分かると思いますのでそちらで。