Categories: Java

【Java入門】StreamAPIの集約操作(sum,max,min,count,average)

IntStreamインターフェースの集約操作

合計を求めるsum

IntStreamで要素の合計を求めるにはsumを使います。

Java

System.out.println("sum関数:" + IntStream.of(1, 2, 3).sum());

実行結果

sum関数:6

最大値を求めるmax

IntStreamで要素の最大値を求めるにはmaxを使います。
maxはOptional型で返すので、int型で返したい場合はgetAsIntを用います。

Java

System.out.println("max関数:" + IntStream.of(1, 2, 3).max().getAsInt());

実行結果

max関数:3

最小値を求めるmin

IntStreamで要素の最小値を求めるにはminを使います。
minはOptional型で返すので、int型で返したい場合はgetAsIntを用います。

Java

System.out.println("min関数:" + IntStream.of(1, 2, 3).min().getAsInt());

実行結果

min関数:1

個数を求めるcount

IntStreamで要素の個数を求めるにはcountを使います。

Java

System.out.println("count関数:" + IntStream.of(1, 2, 3).count());

実行結果

count関数:3

平均を求めるaverage

IntStreamで要素の平均を求めるにはaverageを使います。
averageはOptional型で返すので、Double型で返したい場合はgetAsDoubleを用います。

Java

System.out.println("average関数:" + IntStream.of(1, 2, 3).average().getAsDouble());

実行結果

average関数:2.0

任意のストリームで集約操作を行う

例えば以下のようなfoodクラスのデータを集約する場合を考えてみます。

Java

public class food {

    String name;    //名前
    int price;  //値段
    String group;//カテゴリ

    //コンストラクタ
    public food(String name, int price, String group) {
        super();
        this.name = name;
        this.price = price;
        this.group = group;
    }

    //ゲッター・セッター
    public String getName() { return name;}
    public void setName(String name) {this.name = name;}
    public int getPrice() {return price;}
    public void setPrice(int price) {this.price = price;}
    public String getgroup() {return group;}
    public void setgroup(String group) {this.group = group;}

    @Override
    public String toString(){
        return this.name + ":" + this.price + ":" + this.group;
    }

}

投入するデータは次のとおりとします。

Java

//foodリストの生成
List<food> foodList = new ArrayList<>();

//foodリストにデータを詰める。
foodList.add(new food("キャベツ", 90, "野菜"));
foodList.add(new food("トマト", 130, "野菜"));
foodList.add(new food("ブロッコリー", 200, "野菜"));
foodList.add(new food("リンゴ", 100, "フルーツ"));
foodList.add(new food("オレンジ", 150, "フルーツ"));
foodList.add(new food("ぶどう", 200, "フルーツ"));
foodList.add(new food("イチゴ", 500, "フルーツ"));
foodList.add(new food("チョコレート", 80, "お菓子"));
foodList.add(new food("アメ", 50, "お菓子"));
foodList.add(new food("ケーキ", 1000, "お菓子"));
foodList.add(new food("ポテトチップス", 150, "お菓子"));
foodList.add(new food("クッキー", 120, "お菓子"));

ストリーム内の要素をすべて合計する

ストリーム内の要素をすべて合計にするにはCollectors#summingXxxを使用します。
int型の場合はCollectors#summingIntを使い、Double型の場合はCollectors#summingDoubleを使用します。

Java

Integer result = foodList
        .stream()
        .collect(Collectors.summingInt(food::getPrice));
System.out.println(result);

実行結果

2770

すべて合計すると90+130+200+100+150+200+500+80+50+1000+150+120=2770になります。

ストリーム内の要素をグループ別に合計する

グループ別に合計を求めたい場合はまずCollectors.groupingByでグループ化してからCollectors.summingXxxで合計を求めます。

Java

Map<String, Integer>result = foodList
        .stream()
        .collect(Collectors.groupingBy(food::getgroup,
                Collectors.summingInt(food::getPrice)));
System.out.println(result);

実行結果

{お菓子=1400, 野菜=420, フルーツ=950}

これで、お菓子、野菜、フルーツのそれぞれのグループで合計を求めることが出来ました。

ストリーム内のすべての要素から最大値を取得する

ストリーム内のすべての要素から最大値を取得するにはCollectors.maxByを使用します。

Java

Optional<food> result = foodList
        .stream()
        .collect(Collectors.maxBy(Comparator.comparing(food::getPrice)));

result.ifPresent(s -> System.out.println(s));

実行結果

ケーキ:1000:お菓子

要素の中でpriceが最大値なのはケーキなので、無事取得できました。

ストリーム内の要素からグループ別に最大値を取得する

グループ別に最大値を求めたい場合はまずCollectors.groupingByでグループ化してからCollectors.maxByで最大値を求めます。

Java

Map<String, Optional<food>>result = foodList
                .stream()
                .collect(Collectors.groupingBy(food::getgroup,
                        Collectors.maxBy(Comparator.comparing(food::getPrice))));

for(Optional<food> map : result.values()) {
    map.ifPresent(s -> System.out.println(s));
}

実行結果

ケーキ:1000:お菓子
ブロッコリー:200:野菜
イチゴ:500:フルーツ

これで、お菓子、野菜、フルーツのそれぞれのグループから最大値を持つ要素を取得することが出来ました。

ストリーム内のすべての要素から最小値を取得する

ストリーム内のすべての要素から最小値を取得するにはCollectors.minByを使用します。

Java

Optional<food> result = foodList
        .stream()
        .collect(Collectors.minBy(Comparator.comparing(food::getPrice)));

result.ifPresent(s -> System.out.println(s));

実行結果

アメ:50:お菓子

要素の中でpriceが最大値なのはアメなので、無事取得できました。

ストリーム内の要素からグループ別に最小値を取得する

グループ別に最小値を求めたい場合はまずCollectors.groupingByでグループ化してからCollectors.minByで最小値を求めます。

Java

Map<String, Optional<food>>result = foodList
        .stream()
        .collect(Collectors.groupingBy(food::getgroup,
                Collectors.minBy(Comparator.comparing(food::getPrice))));

for(Optional<food> map : result.values()) {
    map.ifPresent(s -> System.out.println(s));
}

実行結果

アメ:50:お菓子
キャベツ:90:野菜
リンゴ:100:フルーツ

これで、お菓子、野菜、フルーツのそれぞれのグループから最小値を持つ要素を取得することが出来ました。

ストリーム内の要素の個数を求める

ストリーム内の要素の個数を求めるにはCollectors.countingを使用します。

Java

Long result = foodList
        .stream()
        .collect(Collectors.counting());

System.out.println(result);

実行結果

12

ストリーム内の要素の個数をグループ別に求める

ストリーム内の要素の個数をグループ別に求めるにはCollectors.groupingByでグループしてからCollectors.countingを使用します。

Java

Map<String, Long> result = foodList
        .stream()
        .collect(Collectors.groupingBy(food::getgroup,
                Collectors.counting()));

for(Map.Entry<String, Long> map: result.entrySet()) {
    System.out.println(map.getKey() + " : " + map.getValue());
}

実行結果

お菓子 : 5
野菜 : 3
フルーツ : 4

ストリーム内の要素の平均を求める

ストリーム内の要素の平均を求めるにはCollectors.averagingDoubleを使用します。

Java

Double result = foodList
        .stream()
        .collect(Collectors.averagingDouble(food::getPrice));


System.out.println(result);

実行結果

230.83333333333334

ストリーム内の要素の平均をグループ別に求める

ストリーム内の要素の平均をグループ別に求めるにはCollectors.groupingByでグループしてからCollectors.averagingDoubleを使用します。

Java

Map<String, Double> result = foodList
        .stream()
        .collect(Collectors.groupingBy(food::getgroup,
                Collectors.averagingDouble(food::getPrice)));

for(Map.Entry<String, Double> map: result.entrySet()) {
    System.out.println(map.getKey() + " : " + map.getValue());
}

実行結果

お菓子 : 280.0
野菜 : 140.0
フルーツ : 237.5

以上で記事の解説はお終い!

もっとJavaやSpringを勉強したい方にはUdemyがオススメ!同僚に差をつけよう!

issiki_wp