pdeva
pdeva

Reputation: 45491

How to combine these 2 lambdas into a single GroupBy call?

I have a function like this:

 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())));
}

Is there any way to have the groupBy call do the transformation that i do explicitly in line 2 so i dont have to separately stream over the map?

Update
Here is what mergeStats() looks like:

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

Upvotes: 2

Views: 93

Answers (2)

Louis Wasserman
Louis Wasserman

Reputation: 198103

If you can rewrite StatUtils.mergeStats into a Collector, you could just write

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

And even if you can't do this, you could write

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

Upvotes: 3

Eran
Eran

Reputation: 393831

In order to group the PassedMetricData instances, you must consume the entire Stream since, for example, the first and last PassedMetricData might be grouped into the same group.

That's why the grouping must be a terminal operation on the original Stream and you must create a new Stream in order to do the transformation on the results of this grouping.

You could chain these two statements, but it won't make much of a difference :

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())));
}

Upvotes: 1

Related Questions