53
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

コレクションを強化したStream

Streamでなんでもできちゃうんじゃないかな

java8にはコレクションを処理するためにStreamという仕組みが新たに取り入れられました。javaにはjava5で取り入れられた拡張for文がありますが、そんなの比較にならないくらい便利になりました。
まずは基本のforEachから。

ForEach.java
Arrays.asList("a", "b", "c").stream().forEach(s -> System.out.println(s));

Listにstream()というメソッドが追加されました。これはリストに対するStreamを返すメソッドで、Listにdefaultで実装されています。
forEachはStreamの全要素に対して引数の関数を適用しています。引数の無名関数はprintlnを呼ぶだけのラッパーで、実行するとコンソールにa b cと表示されます。
さて、これだけだと何も便利になった感じがしないですね。むしろ拡張for文の方がわかりやすいです。

java.util.stream.Stream

StreamインターフェイスにはforEach以外にも色々なメソッドが実装されています。ここでは例としてmapToIntfilterを使ってみます。

Sum.java
List<String> nums = asList("1", "2", "3");

int sum = nums.stream()
            .mapToInt(Integer::parseInt)
            .filter(i -> i % 2 == 1)
            .sum();

mapToIntはstreamの要素を引数にしてintを返す関数を引数に取ります。この例だと、streamはString型なので、mapToIntint xxx(String s)という関数を引数に受け取ります。mapToIntはstreamの要素1つ1つに引数で受け取った関数を適用していきます。つまり数字文字列のリストが数値リストに変換されます。
次にfilterが実行されます。filterはstreamの要素を受け取ってbooleanを返す関数を受け取ります。そして関数の結果がtrueである要素だけを収集します。この例では奇数だけが収集されて、2は捨てられます。
最後にstreamの要素すべてを加算します。
結果は4になります。
絵で書くとこんな感じです。

Sum2.java
元のリスト           mapToInt    filter    sum
["1", "2", "3"] -> [1, 2, 3] -> [1, 3] -> 4

これと同じ処理をjava7で書くと

java.SumJava7.java
int total = 0;
for (String i : nums) {
    int num = Integer.parseInt(i);
    if (num % 2 == 1) {
        total += num;
    }
}

こんな感じになります。
java8では「数値に変換して」「奇数を集めて」「足し込む」とここの小さい処理をくっつけて大きな処理を作る事ができます。

Streamには他にも以下のようなメソッドが用意されています。

メソッド 動き
allMatch streamの全要素が指定の条件(関数)を満たすかどうかをチェックする
anyMatch streamの要素のうち1つでも指定の条件(関数)を満たすかどうかをチェックする
concat 2つのstreamを結合する
count List.size()的なもの
distinct equalsを使用して、streamから重複データを省く
filter 指定した条件に合致する要素のみを収集する
map 要素を別の値に変換する関数A->Bを渡してStream<A>からStream<B>を作成する
forEach 指定した関数を全要素に対して実行していく
max, min 比較関数を渡して、要素内の最大値や最小値を取得する
reduce 2つの要素を1つにまとめる関数を引数にとって、全要素を1つの要素に集約する

これらは「この中から最大値を取得する」みたいな大枠の動作しか提供しません。コレクションの中で「何を最大値とするか?」といった実際の処理は引数で渡します。実際の処理を外部から与えられるので、すごく柔軟に大きな処理を組み立てられるようになっています。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
53
Help us understand the problem. What are the problem?