【Java】Stream APIの基本 streamを使ってリスト操作を楽にしよう!

アイキャッチ画像

ストリーム(stream)とは

ストリームとは、Java 8で導入された機能で、コレクションなどのデータを関数型スタイルで処理するためのAPIです。データをループで処理する代わりに、宣言的(何をしたいか)に書けるのが特徴です。

Stream API の基本概念

  • Streamは、データの要素を「順番に」「一方向に」処理する操作のパイプライン
  • 元のデータ(リストなど)を変更しない
  • 中間操作(filter, mapなど)と終端操作(forEach, collectなど)を組み合わせて使う

Stream APIの代表例

filterメソッド:条件で絞り込む

名前のとおり、フィルターをかけて要素をふるいにかけるイメージです。

条件にあてはまった要素だけを残した新たなコレクションを生成します。

(例1)

まずは一番簡単な例

操作:Integerのリストの要素の中から3以上の要素だけ絞り込み。

List<Integer> strm1 = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
List<Integer> strm2 = strm1.stream().filter(s -> s >= 3).collect(Collectors.toList());
System.out.println(strm1);// [1, 2, 3, 4, 5, 6]
System.out.println(strm2);// [3, 4, 5, 6]

リスト内のうち「3以上」にあてはまっていない1と2が消えていますね。

・説明

1行目では、要素の型がIntegerのArrayList(変数名strm1)を初期化しているだけです。

2行目で、さきほど作ったstrm1に対しstream()を使います。これはstreamを使う時に必須です!!

慣れてくると後半の処理に気を取られて意外と忘れがちなので注意。

次に、使いたいstreamのメソッドをつなげます。ここでは要素の絞り込みなのでfilter()です。

ここのfilterやmap、

ここで、filterの中がラムダ式と呼ばれる記述法になっています。なんだか難しそうですが、以下のようになっているだけです。

・ラムダ式
(引数名) -> { 条件 }

// 具体的なコード例
filter(s -> s >= 3) // 3以上の要素
filter(s -> s % 2 == 0) // 偶数(2で割って余り0)
filter(x -> x < 0 && x % 5 != 0) // 0未満かつ5の倍数でない

引数の名前はなんでもいいです。実際の現場でもアルファベット1文字だけのケースがあります。

このfilerメソッドで、要素の絞り込みはできました。しかし、これだけではリスト型として生成することができません。なので、最後に終端操作とよばれるものを行います。

またまた難しそうな名前でですが、単に「変換・判定などの各種処理」を行っているだけです。

(例1)のcollect(Collectors.toList())は、最終的にリストに戻す(再リスト化)操作です。

数字以外の要素にもfilterを使ってみましょう!

文字列に”e”が入っているものだけ

List<String> strm3 = new ArrayList<>(Arrays.asList(“model”, “view”, “controller”, “spring”, “java”));
List<String> strm4 = strm3.stream().filter(s -> s.contains(“e”)).collect(Collectors.toList());
System.out.println(strm3);// [model, view, controller, spring, java]
System.out.println(strm4);// [model, view, controller]

mapメソッド:すべての要素に同一処理

リストの中の要素すべてに同じ処理をしたい状況は多々あると思います。

for文で全要素を取り出してそれぞれに処理をすることも一応可能ですが、mapメソッドを使えばもっと楽に処理ができます。

リスト内のすべての数字を二乗

List<Integer> strm5 = new ArrayList<>(Arrays.asList(-2, -1, 0, 1, 2, 10));
List<Integer> strm6 = strm5.stream().map(n -> n*n).collect(Collectors.toList());
System.out.println(strm5);// [-2, -1, 0, 1, 2, 10]
System.out.println(strm6);// [4, 1, 0, 1, 4, 100]

distinctメソッド:重複要素を削除

リストの中の重複要素を削除します。

List<String> strm7 = new ArrayList<>(Arrays.asList(“T”, “I”, “E”, “C”, “H”, “T”, “C”, “T”, “N”));
List<String> strm8 = strm7.stream().distinct().collect(Collectors.toList());
System.out.println(strm7);// [T, I, E, C, H, T, C, T, N]
System.out.println(strm8);// [T, I, E, C, H, N]

まとめ

今回の記事ではStream APIの基本であるfilter、map、distinctについて紹介しました。

まだまだ紹介しきれないメソッドや使い方があるので、気になる人はチェックしていただけたら幸いです。