如何将这两个lambda组合成一个GroupBy调用?

时间:2014-08-06 17:17:53

标签: java lambda java-8 java-stream

我有这样的功能:

 private static  Map<String, ResponseTimeStats> perOperationStats(List<PassedMetricData> scopedMetrics, Function<PassedMetricData, String> classifier)
{
    Map<String, List<PassedMetricData>> operationToDataMap = scopedMetrics.stream()
            .collect(groupingBy(classifier));


    return operationToDataMap.entrySet().stream()
            .collect(toMap(Map.Entry::getKey, e -> StatUtils.mergeStats(e.getValue())));
}

有没有办法让groupBy调用我在第2行显式执行的转换,所以我不必单独流式传输地图?

更新
以下是mergeStats()的样子:

public static ResponseTimeStats mergeStats(Collection<PassedMetricData> metricDataList) 
{
    ResponseTimeStats stats = new ResponseTimeStats();
    metricDataList.forEach(data -> stats.merge(data.stats));
    return stats;
}

2 个答案:

答案 0 :(得分:3)

如果您可以将StatUtils.mergeStats重写为Collector,则可以写

return scopedMetrics.stream().collect(groupingBy(classifier, mergeStatsCollector));

即使你不能这样做,你也可以写

return scopedMetrics.stream().collect(groupingBy(classifier,
    collectingAndThen(toList(), StatUtils::mergeStats)));

答案 1 :(得分:1)

为了对PassedMetricData个实例进行分组,您必须使用整个Stream,因为例如,第一个和最后一个PassedMetricData可能会被分组到同一个组中。

这就是为什么分组必须是原始Stream上的终端操作的原因,您必须创建一个新的Stream才能对此分组的结果进行转换。

你可以将这两个陈述联系起来,但它不会产生太大的影响:

private static  Map<String, ResponseTimeStats> perOperationStats(List<PassedMetricData> scopedMetrics, Function<PassedMetricData, String> classifier)
{
    return scopedMetrics.stream()
        .collect(groupingBy(classifier)).entrySet().stream()
            .collect(toMap(Map.Entry::getKey, e -> StatUtils.mergeStats(e.getValue())));
}