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

You can create a class Company and then subsequent operations become much simpler.

class Company {
    String company;
    String billType;
    String billPeriod;

    public Company(String company, String billType, String billPeriod) {
        this.company = company;
        this.billType = billType;
        this.billPeriod = billPeriod;
    }

    // getters, setters, toString, etc
}

Initialize the list :

List<Company> list = new ArrayList<>();
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "B", "01-2019"));
list.add(new Company("LG", "B", "01-2019"));
list.add(new Company("Samsung", "A", "10-2018"));
list.add(new Company("Samsung", "A", "10-2018"));
list.add(new Company("Samsung", "B", "11-2018"));

Now for an example, you can group by company name :

Map<String, Long> map = list.stream().collect(
        Collectors.groupingBy(Company::getCompany, 
                              Collectors.mapping((Company c) -> c, Collectors.counting())));

Now it becomes much easier to perform other operations as you desire. Also, here instead of creating 8 maps you end up dealing with just 1 list.


It's really difficult to grouping and counting a map because your map data will be changed after you increase your counter value. Therefore, you must save the original data of the map, and save your counter value to the another map. Join 2 maps after your counting process is complete.

Map<Map<String, Object>, Long> counterData = listBeforeGroup.stream().collect(Collectors.groupingBy(m -> m, Collectors.counting()));

List<Map<String, Object>> listAfterGroup = new ArrayList<>();
for (Map<String, Object> m : counterData.keySet()) {
    Map<String, Object> newMap = new HashMap<>(m);
    newMap.put("count", counterData.get(m));
    listAfterGroup.add(newMap);
}

Update Java 8 approach, not easy to debug

List<Map<String, Object>> listAfterGroup = listBeforeGroup.stream().collect(Collectors.groupingBy(m -> m, Collectors.counting())).entrySet().stream().map(e -> {
    Map<String, Object> newMap = e.getKey();
    newMap.put("count", e.getValue());
    return newMap;
}).collect(Collectors.toList());