object 的 Sum 属性与 Stream API

Sum attribute of object with Stream API

我目前有以下情况:

我有一个 Report object 可以包含多个 Query object。 Query object 具有以下属性:Optional<Filter> comparisonFilterOptional<String> filterChoiceint queryOutput

并非每个查询都有比较过滤器,所以我首先检查一下。然后,我确保获得针对特定过滤器的查询(这不是这里的问题,因此我不会详细讨论)。每个过滤器都有一些选择,其中选择的数量是可变的。

这里是输入的例子(这些Queryobject都有相同的comparisonFilter):

Query 1 -- Choice: 'First' -- Output: 10
Query 1 -- Choice: 'First' -- Output: 5
Query 1 -- Choice: 'Second' -- Output: 25
Query 1 -- Choice: 'Third' -- Output: 10

现在,我想对每个唯一选择的查询输出求和。我目前有这个代码:

report
.getQueries()
.stream()
.filter(q -> q.getComparisonFilter().isPresent())
.filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get()))
.forEach(query -> {

    //Sum the query outputs per choice

});

我可以通过创建一个 Map<String, Integer> 来做到这一点,其中键是选择,值是查询输入。但是然后我需要再次遍历 Map 以使用某些东西的值(这在这里并不重要)。

输出应该是这样的:

Choice: 'First' -- Summed Output: 15
Choice: 'Second' -- Summed Output: 25
Choice: 'Third' -- Summed Output: 10

但我想直接在直播中的 forEach 中使用这个 'Summed Output',但如果这不再可行或不实用,我可以接受。

我想以 'Java 8' 的方式执行此操作,但我似乎无法找到方法。

所以我的问题是:是否可以使用新的 Stream API 缩短此时间?

注意:如果有人对我如何使这个问题更笼统(可能是更好的标题和一些概括)有一些想法,请告诉我!

如果我理解得很好,你确实在寻找一个 groupingBy 然后你必须通过对它们的 int 属性.

求和来对这些值进行分组

groupingBy 会给你一个 Map<String, List<Query>> 但随后下游收集器(在这种情况下为 Collectors.summingInt )将对 [=17 的所有 int 值求和=] 列表中的实例,导致 Map<String, Integer>.

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;
...

Map<String, Integer> map = 
    report.getQueries()
          .stream()
          .filter(q -> q.getComparisonFilter().isPresent())
          .filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get()))
          .collect(groupingBy(q -> q.filterChoice.get(), summingInt(q -> q.queryOutput)));

请注意,您应该检查 filterChoice 可选是否不为空(也许添加另一个 filter 子句?)。你可以看到这个小gist一个基本和简化的演示来说明原理。

此外,Optional class 提供了 equals 的合理实现,因此过滤器子句可能如下所示:

.filter(q -> q.getComparisonFilter().equals(view.getFilter()))