Skip to content

A list of maps group by and sum up with a certain key

I would like to make a list of maps being grouped by and summed up with a certain key.

List<Tag> tagList = new ArrayList<>();

# Tag
HashMap<String, Object> tagMap = new HashMap<>();

## feeding data example
tagMap.put("category", "A");
tagMap.put("name", "Apple");
tagMap.put("price", 10);

tagList.add(tagMap)

tagList = 
    [
      {
        "category": "A",
        "name": "apple",
        "price": 10
      },
      {
        "category": "B",
        "name": "banana",
        "price": 20
      },
      {
        "category": "C",
        "name": "candy",
        "price": 30
      },
      {
        "category": "A",
        "name": "apple",
        "price": 20
      },
      {
        "category": "B",
        "name": "banana",
        "price": 10
      },
      {
        "category": "C",
        "name": "candy",
        "price": 20
      }
    ]

I ve already grouped tagList by category

Map<String, List<Tag>> tagGrouped =
       tagList.stream()
       .collect(Collectors.groupingBy(tag -> tag.getCategory()));

Here is the example

Map<String, List<Tag>> tagGrouped =

        {
          "A": [
            {
              "category": "A",
              "name": "apple",
              "price": 10
            },
            {
              "category": "A",
              "name": "apple",
              "price": 20
            },
            {
              "category": "A",
              "name": "apple",
              "price": 30
            }
          ],
          "B": [
            {
              "category": "B",
              "name": "banana",
              "price": 10
            },
            {
              "category": "B",
              "name": "banana",
              "price": 20
            }
          ],
          "C": [
            {
              "category": "C",
              "name": "candy",
              "price": 10
            },
            {
              "category": "C",
              "name": "candy",
              "price": 10
            },
            {
              "category": "C",
              "name": "candy",
              "price": 20
            }
          ]
    }

This is the sample output that I want to get finally

tagGroupedList = 
    [
      {
        "category": "A",
        "name": "apple",
        "price": 60
      },
      {
        "category": "B",
        "name": "banana",
        "price": 30
      },
      {
        "category": "C",
        "name": "candy",
        "price": 40
      }
    ]

I got stuck at this point..

List<Tag> tagGroupedList =
                tagGrouped.stream()
                .collect(Collectors.groupingBy(Tag::getCategory))
                .entrySet()
                .stream()
                .flatMap(e -> e.getValue().stream())
                .collect(Collectors.summarizingInt(Tag::getPrice));

Answer

This is similar to your previous question

Collection<Tag> tagGroupedList  = tagGrouped.values().stream().flatMap(tags -> tags.stream()).collect(Collectors.toMap(tag -> tag.getCategory(), Function.identity(), (tag1, tag2) -> {
        tag1.setPrice(tag1.getPrice() + tag2.getPrice());
        return tag1;
    })).values();
   //tagGroupedList will have the data what you need