M
M
mitaichik2018-02-22 18:51:48
Java
mitaichik, 2018-02-22 18:51:48

Java Stream: Is it possible to do object aggregation?

There is a list of object objects:

{type : CAT, count : 1},
{type : CAT, count : 2},
{type : DOG, count : 5},

You need to get aggregated data, that is, collect all objects with the same type into one, and summarize the count field. That is, the output should be
{type : CAT, count : 3},       // 1 + 2
{type : DOG, count : 5},

Can this be done using the Stream API?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sergey Gornostaev, 2018-02-22
@mitaichik

The author of the question is lost, I will have to offer possible options. I'll start with the simplest - grouping in the Map with the appropriate collector:

Map<String, Integer> map = list.stream()
                                .collect(Collectors.toMap(Animal::getType,
                                                          Animal::getCount,
                                                          (a, b) -> a + b));

A slightly more complex, though simpler-looking, but much more flexible option is a grouping collector:
Map<String, Integer> map = list.stream()
                               .collect(Collectors.groupingBy(Animal::getType, 
                                                              Collectors.summingInt(Animal::getCount)));

Well, a very low-level option - writing your own collector:
List<Animal> aggregated 
  = list.stream()
        .collect(Collector.of(HashMap<String, Integer>::new,
                              (acc, val) -> acc.compute(val.getType(), (k, v) -> v == null ? val.getCount() : v + val.getCount()),
                              (l, r) -> {
                                  l.replaceAll((k, v) -> v + r.getOrDefault(k, 0));
                                  return l;
                              },
                              acc -> acc.entrySet()
                                        .stream()
                                        .map(e -> new Animal(e.getKey(), e.getValue()))
                                        .collect(Collectors.toList())));

D
Dmitry Eremin, 2018-02-22
@EreminD

You-breath!

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question