【问题标题】:How to combine these 2 lambdas into a single GroupBy call?如何将这 2 个 lambda 表达式组合成一个 GroupBy 调用?
【发布时间】:2014-08-06 17:17:53
【问题描述】:

我有这样的功能:

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

【问题讨论】:

  • StatUtils.mergeStats 是做什么的?
  • 我现在已经在问题中添加了mergeStats 实现
  • 收集器必须能够并行化,这看起来不像你可以用你的 mergeStats 实现,因为它是当前编写的,因为没有办法组合两个 ResponseTimeStats。但是您仍然可以使用我回答中的第二种方法。

标签: java lambda java-8 java-stream


【解决方案1】:

如果你可以将StatUtils.mergeStats 改写成Collector,你可以直接写

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

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

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

【讨论】:

  • 我不确定这是否可能,因为我假设mergeStatsCollector 需要属于同一组的所有PassedMetricData 对象才能生成ResponseTimeStats
  • 我们无法确定这一点,但我不一定认为——大多数类型的“合并”应该可以通过Collector 实现。
  • @Eran:添加的方法即使是这种情况也可以一次性使用。
  • 有趣。看起来它可能会起作用。 +1。如果 OP 确认它有效,我将删除我的答案。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    相关资源
    最近更新 更多