Home » Java » Java: Group By then Map

Java: Group By then Map

Posted by: admin December 28, 2021 Leave a comment


I have a stream of Events

public class Event {
    Location location;
    double turnout;
    //... other fields & getters

And a statistics class EventStatistics

public class EventStatistics {
    // Stats properties e.g. turnout standard deviation/median

    public EventStatistics(List<Event> events) {
        // Generate stats

I need to group all the events by location & create a map of location and event statistics Map<Location, EventStatistics>

The group by is just:

Map<Location, List<Event>> byLocation = events.stream().collect(groupingBy(Event::getLocation));

I know there is an overloaded groupingBy(function, collector) collector. Can I use somehow this to generate my Map<Location, EventStatistics> in a single stream?


All you need is collectingAndThen:

Map<Location, EventStatistics> result = 


You can construct your own Collector using Collector.of(...), like this:

Map<Location, EventStatistics> collect = events.stream().collect(groupingBy(Event::getLocation,
                     (left, right) -> { left.addAll(right); return left; },


If your EventStatistics were to be able to accept single Events instead of a full list, and a method to merge two statistics, as in

EventStatistics {
    public EventStatistics() {}
    public void addEvent(Event e);
    public EventStatistics merge(EventStatistics toMerge);

then you can do

groupingBy(Event::getLocation, Collector.of(EventStatistics::new, EventStatistics::accept, EventStatistics::merge));

Here, the argument-less constructor is the Supplier, the accept is the accumulator, and the merge is the combiner.