StreamAPIについて調べてみた collect編 その2

【前提条件】

[環境]

【概要】

今回はCollectorsクラスのメソッドについて調べてました。

Collectorsクラスのうち、
個人的に良く使いそうだなと思ったものを
取り上げてみ見ます。

【変換系メソッド】

Collectionsのクラスに変換するメソッドがいくつか用意されています。

[ソース]
    public static void main(final String[] args) {

        final List<String> list = new ArrayList<>();

        list.add("one");
        list.add("two");
        list.add("three");

        final Set<String> convertedSet = list.stream().collect(Collectors.toSet());
        convertedSet.forEach(System.out::println);

        final List<String> convetedList = convertedSet.stream().collect(Collectors.toList());
        convetedList.forEach(System.out::println);

        final Map<String, String> conveterdMap =
                list.stream().collect(Collectors.toMap(v -> "key-" + v, v -> "value-" + v));

        conveterdMap.forEach((k, v) -> System.out.println("[" + k + "][" + v + "]"));
    }

toSetメソッドはSetに、toListメソッドはListに、toMapメソッドはMapに変換します。

toSet/toListメソッドはパラメータは不要ですが、
toMapメソッドはパラメータが必要です。

toMapメソッドはFunctionインターフェイスのオブジェクトを
パラメータとして受け取ります。
最初のパラメータがMapのキーに変換する関数を、
最後のパラメータがMapの値に変換する関数を渡します。

[実行結果]
one
two
three
one
two
three
[key-three][value-three]
[key-one][value-one]
[key-two][value-two]

【集計系メソッド】

つづいて集計を行うためのメソッドです。

[やり方 その1]
    public static void main(final String[] args) {

        final List<Integer> list = new ArrayList<>();

        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);

        final long count = list.stream().collect(Collectors.counting());
        System.out.println(count);

        final int summing = list.stream().collect(Collectors.summingInt(v -> v));
        System.out.println(summing);

        final Optional<Integer> max = list.stream().collect(Collectors.maxBy((v1, v2) -> v1 > v2 ? 0 : -1));
        System.out.println(max.get());

        final Optional<Integer> min = list.stream().collect(Collectors.minBy((v1, v2) -> v1 > v2 ? 0 : -1));
        System.out.println(min.get());

        final Double average = list.stream().collect(Collectors.averagingInt(v -> v));
        System.out.println(average);
    }

countingメソッドは個数をカウントします。
filterなどで絞り込んだ件数を取得する場合に使います。

summingIntメソッドは値を合計してintで返却します。
パラメータにはintに変換するための関数を渡します。
今回はListの中身がintなので、受け取ったパラメータをそのまま返却する関数を渡しています。

maxBy/minByメソッドはそれぞれ最大と最小を取得します。
パラメータはComparetorインターフェイスのオブジェクトです。

averageingIntメソッドは平均を取得します。

[やり方 その2]

その1のやり方では個別にメソッドを実行していましたが、
同時に取得する方法があります。

    public static void main(final String[] args) {

        final List<Integer> list = new ArrayList<>();

        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);

        final IntSummaryStatistics summary = list.stream().collect(Collectors.summarizingInt(v -> v));
        System.out.println(summary.getCount());
        System.out.println(summary.getSum());
        System.out.println(summary.getMax());
        System.out.println(summary.getMin());
        System.out.println(summary.getAverage());
    }

summarizingIntメソッドを使うと集計結果を保持したオブジェクトが返ってきます。
パラメータはintに変換するための関数です。

[実行結果]

やり方その1とその2で同じ結果が返ってきます。

4
16
7
1
4.0

【reducingメソッド】

reducingメソッドはcollectで受け取った要素のデータに対して
処理を行うことができます。

[ソース]
    public static void main(final String[] args) {

        final List<Integer> list = new ArrayList<>();

        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);

        Optional<Integer> reduceResult =
                list.stream().collect(Collectors.reducing((accumrator, value) -> accumrator * value));
        System.out.println(reduceResult.get());
    }

reducingメソッドのパラメータは
元となるCollectionの型のオブジェクトを2つ受け取ります。

片方はアキュムレータで、片方はCollectionのオブジェクトです。
サンプルではリストの中身を全て掛け合わせて返却しています。

[実行結果]
105

【joiningメソッド】

joiningメソッドはCollectionの要素を結合するメソッドです。

collectメソッドで受け取るオブジェクトが
CharSequenceインターフェイスのオブジェクトの場合にのみ使用できます。

[ソース]
    public static void main(final String[] args) {

        final List<String> list = new ArrayList<>();

        list.add("one");
        list.add("two");
        list.add("three");

        final String join1Value = list.stream().collect(Collectors.joining());
        final String join2Value = list.stream().collect(Collectors.joining(","));
        final String join3Value = list.stream().collect(Collectors.joining(",", "(", ")"));

        System.out.println(join1Value);
        System.out.println(join2Value);
        System.out.println(join3Value);
    }

joiningメソッドは3つのパターンがあります。

パラメータなしの場合はCollectionの中身を結合します。

パラメータが1つの場合はパラメータで受け取った値を
デリミタとして中身を結合します。

パラメータが3つの場合、
一つ目がデリミタ、二つ目がプレフィックス、三つ目がサフィックスです。

[実行結果]
onetwothree
one,two,three
(one,two,three)

【まとめ】

変換系のメソッドが一番使いそうなので、
覚えておくべきものだと思います。

それ以外のメソッドについてもバッチ処理では
よく使いそうなものばかりなので
覚えておいた方が良さそうです。