web-dev-qa-db-ja.com

Java 8 List <Map <String、Object >> to List <Map <String、Object >> group by key and count by value

次の地図のリストがあります

List<Map<String, Object>> listBeforeGroup = new ArrayList<Map<String, Object>>();

    Map<String, Object> m1 = new HashMap<String, Object>();
    m1.put("company", "LG");
    m1.put("billType", "A");
    m1.put("billPeriod", "09-2018");

    Map<String, Object> m2 = new HashMap<String, Object>();
    m2.put("company", "LG");
    m2.put("billType", "A");
    m2.put("billPeriod", "09-2018");

    Map<String, Object> m3 = new HashMap<String, Object>();
    m3.put("company", "LG");
    m3.put("billType", "A");
    m3.put("billPeriod", "09-2018");

    Map<String, Object> m4 = new HashMap<String, Object>();
    m4.put("company", "LG");
    m4.put("billType", "B");
    m4.put("billPeriod", "01-2019");

    Map<String, Object> m5 = new HashMap<String, Object>();
    m5.put("company", "LG");
    m5.put("billType", "B");
    m5.put("billPeriod", "01-2019");

    Map<String, Object> m6 = new HashMap<String, Object>();
    m6.put("company", "Samsung");
    m6.put("billType", "A");
    m6.put("billPeriod", "10-2018");

    Map<String, Object> m7 = new HashMap<String, Object>();
    m7.put("company", "Samsung");
    m7.put("billType", "A");
    m7.put("billPeriod", "10-2018");

    Map<String, Object> m8 = new HashMap<String, Object>();
    m8.put("company", "Samsung");
    m8.put("billType", "B");
    m8.put("billPeriod", "11-2018");

    listBeforeGroup.add(m1);listBeforeGroup.add(m2);
    listBeforeGroup.add(m3);listBeforeGroup.add(m4);
    listBeforeGroup.add(m5);listBeforeGroup.add(m6);

この出力を取得するにはどうすればよいですか?

    //Desired Output - List<Map<String, Object>>
    //{company=LG, billType=A, billPeriod=09-2018, count=3}
    //{company=LG, billType=B, billPeriod=01-2019, count=2}
    //{company=Samsung, billType=A, billPeriod=10-2018, count=2}
    //{company=Samsung, billType=B, billPeriod=11-2018, count=1}

Java 8ストリームを使用してこれを試しましたが、目的の出力を取得できません

List<Map<String, Object>> listAfterGroup = listBeforeGroup.stream().map(m -> m.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p - >  p.getValue()))).collect(Collectors.toList());

これを試したところ、この解決策はマップを提供しますが、私はこれを望んでいません

Map<Object, Long> listAfterGroup = listBeforeGroup.stream().flatMap(m -> m.entrySet().stream()).collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.counting()));

たとえば、「billPeriod」というキーでマップをグループ化し、値でアイテムをカウントして、マップの新しいリストを生成します。

7
jhuamanchumo

Java 8での私のアプローチ:

    Function<Map<String, Object>, String> createHashKey = map ->
                     map.values().stream()
                    .map(val -> String.valueOf(val))
                    .collect(Collectors.joining());

    BinaryOperator<Map<String, Object>> mergeDuplicate = (map1, map2) -> {
        int incrementedCount = (int)map1.get("count") + 1;
        map1.put("count", incrementedCount);
        return map1;
    };

    List<Map<String, Object>> listAfterGroup = listBeforeGroup.stream()
            .collect(Collectors.toMap(createHashKey, el -> {
                        el.put("count", 1);
                        return el;
            },mergeDuplicate))
          .values().stream()
          .collect(toList());

多分、最も簡潔な解決策ではないかもしれませんが、コードのロジックを理解するのは非常に読みやすく、簡単に理解できると思います。

0
mwdev