Java 8 - ストリームコレクタグループ化の例

この記事では、Java 8 Streamの Collectors`を使用して、 List`をグループ化、カウント、合計、ソートする方法を説明します。

1.グループ化、カウント、ソート

1.1 `List`でグループ化し、その総数を表示します。

Java8Example1.java

package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example1 {

    public static void main(String[]args) {

       //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        System.out.println(result);


    }
}

出力

{
    papaya=1, orange=1, banana=2, apple=3
}

1.2並べ替えを追加する。

Java8Example2.java

package com.mkyong.java8;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example2 {

    public static void main(String[]args) {

       //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        Map<String, Long> finalMap = new LinkedHashMap<>();

       //Sort a map and add to finalMap
        result.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue()
                        .reversed()).forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));

        System.out.println(finalMap);


    }
}

出力

{
    apple=3, banana=2, papaya=1, orange=1
}

リストオブジェクト

ユーザーが定義したオブジェクトのリストを「グループ化」する例

2.1 Pojo。

Item.java

package com.mkyong.java8;

import java.math.BigDecimal;

public class Item {

    private String name;
    private int qty;
    private BigDecimal price;

   //constructors, getter/setters
}

2.2グループ名で数量を数える

Java8Examples3.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Java8Examples3 {

    public static void main(String[]args) {

       //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
        );

        Map<String, Long> counting = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.counting()));

        System.out.println(counting);

        Map<String, Integer> sum = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.summingInt(Item::getQty)));

        System.out.println(sum);

    }
}

出力

…​.//Group by + Count { papaya=1, banana=2, apple=3, orang=1, watermelon=1 } { papaya=20, banana=30, apple=40, orang=10, watermelon=10 }

2.2グループ別価格 -  `Collectors.groupingBy`と` Collectors.mapping`の例

Java8Examples4.java

package com.mkyong.java8;

import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors;

public class Java8Examples4 {

public static void main(String[]args) {
//3 apple, 2 banana, others 1
 List<Item> items = Arrays.asList(
         new Item("apple", 10, new BigDecimal("9.99")),
         new Item("banana", 20, new BigDecimal("19.99")),
         new Item("orang", 10, new BigDecimal("29.99")),
         new Item("watermelon", 10, new BigDecimal("29.99")),
         new Item("papaya", 20, new BigDecimal("9.99")),
         new Item("apple", 10, new BigDecimal("9.99")),
         new Item("banana", 10, new BigDecimal("19.99")),
         new Item("apple", 20, new BigDecimal("9.99"))
         );
//group by price
 Map<BigDecimal, List<Item>> groupByPriceMap =
     items.stream().collect(Collectors.groupingBy(Item::getPrice));
System.out.println(groupByPriceMap);
//group by price, uses 'mapping' to convert List<Item> to Set<String>
 Map<BigDecimal, Set<String>> result =
         items.stream().collect(
                 Collectors.groupingBy(Item::getPrice,
                         Collectors.mapping(Item::getName, Collectors.toSet())
                 )
         );
System.out.println(result);
    }
}
出力

{ 19.99=[ Item{name='banana', qty=20, price=19.99}, Item{name='banana', qty=10, price=19.99} ], 29.99=[ Item{name='orang', qty=10, price=29.99}, Item{name='watermelon', qty=10, price=29.99} ], 9.99=[ Item{name='apple', qty=10, price=9.99}, Item{name='papaya', qty=20, price=9.99}, Item{name='apple', qty=10, price=9.99}, Item{name='apple', qty=20, price=9.99} ]} { 19.99=[banana], 29.99=[orang, watermelon], 9.99=[papaya, apple]}

=== 参考文献

.  https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html[Java

8ストリームコレクタJavaDoc]。リンク://java/how-to-sort-a-map-in-java/[Java  - マップのソート方法]

.  http://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values-java[Stackoverflow

 - マップを値でソートする(Java)

リンク://タグ/コレクター/[コレクター]リンク://タグ/グループ別/[グループ別]リンク://タグ/java8/[java8]リンク://タグ/ストリーム/[ストリーム]