Java:Group By Then Map

时间:2018-03-10 08:20:08

标签: java stream java-stream

我有一个Event s

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

统计课程EventStatistics

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

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

我需要按位置对所有事件进行分组。创建位置和事件统计信息的地图Map<Location, EventStatistics>

小组是:

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

我知道有一个超载的groupingBy(function, collector)收藏家。我可以用某种方式在单个流中生成Map<Location, EventStatistics>吗?

3 个答案:

答案 0 :(得分:8)

您所需要的只是collectingAndThen

Map<Location, EventStatistics> result = 
    events.stream()
          .collect(Collectors.groupingBy(Event::getLocation,
                                         Collectors.collectingAndThen(
                                             Collectors.toList(), 
                                             EventStatistics::new)));

答案 1 :(得分:1)

如果您的EventStatistics能够接受单个Events而不是完整列表,并且有合并两个统计信息的方法,例如

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

然后you can do

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

此处,无参数构造函数为Supplieracceptaccumulatormergecombiner

答案 2 :(得分:1)

您可以使用Collector构建自己的Collector.of(...),如下所示:

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