使用Stream API汇总对象的属性 [英] Sum attribute of object with Stream API
问题描述
我目前遇到以下情况:
我有一个报告
对象,其中包含多个查询
对象。 查询
对象具有以下属性:可选<过滤器> comparisonFilter
,可选< String> filterChoice
和 int queryOutput
。
I have got a Report
object which can contain multiple Query
objects. The Query
objects have properties: Optional<Filter> comparisonFilter
, Optional<String> filterChoice
and int queryOutput
.
并非每个查询都有比较过滤器,所以我首先检查一下。然后,我确保我得到了特定过滤器的查询(这不是问题,所以我不会详细讨论)。每个过滤器都有一些选择,其中选项的数量是可变的。
Not every query has a comparison filter, so I first check on that. Then, I make sure I get the queries for a particular filter (which is not the problem here, so I will not discuss this in detail). Every filter has some choices, of which the number of choices is variable.
以下是输入的示例(这些查询
对象都具有相同的comparisonFilter):
Here is an example of the input (these Query
objects all have the same 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
现在,我想对每个唯一选择的查询输出求和。我目前有这个代码:
Now, I would like to sum the query outputs for every unique choice. I currently have this code:
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
来使用某些值(这里不重要)。
I could do this by creating a Map<String, Integer>
, where the key is the choice and the value is the query input. But then I would need to loop through the Map
again to use the value for something (which is not important here).
输出应该是这样的:
Choice: 'First' -- Summed Output: 15
Choice: 'Second' -- Summed Output: 25
Choice: 'Third' -- Summed Output: 10
但是我想直接在流上的 forEach
中使用这个'Summed Output',但如果这不可能或不再实用,我没关系那个。
But I would like to use this 'Summed Output' directly in a forEach
on the stream, but if this is not possible or practical anymore, I am okay with that.
我想用'Java 8'方式做这个,但我似乎无法弄清楚如何。
I would like to do this the 'Java 8'-way, but I can not seem to find out how.
所以我的问题是:是否可以使用新的Stream API缩短版本?
注意:如果有人有一些关于如何让这个问题更通用的想法(也许是一个更好的标题和一些概括),请告诉我!
Note: If anyone has some ideas about how I could make this question more general (maybe a better title and some generalizations), please let me know!
推荐答案
<如果我理解得很好,你确实在寻找 groupingBy
,然后你必须通过对它们的int属性求和来对这些值进行分组。
If I understand well, you are indeed looking for a groupingBy
and then you have to group the values by summing their int property.
groupingBy
会给你一个 Map< String,List< Query>>
但是接下来的收集器( Collectors.summingInt
在这种情况下)将汇总查询
int 值>列表中的实例,产生 Map< String,Integer>
。
The groupingBy
will give you a Map<String, List<Query>>
but then the downstream collector (Collectors.summingInt
in this case) will sum all the int
values of the Query
instances in the list, resulting in a 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
可选不为空(可能添加另一个过滤器
子句?)。您可以看到这个小的要点,以获得基本和简化的演示来说明原理。
Note that you should check whether the filterChoice
Optional is not empty (maybe add another filter
clause?). You can see this small gist for a basic and simplified demo to illustrate the principle.
此外可选
类提供合理的等于
的实现,因此过滤器子句可能如下所示:
Also the Optional
class provide a sensible implementation of equals
so the filter clause could looks like this:
.filter(q -> q.getComparisonFilter().equals(view.getFilter()))
这篇关于使用Stream API汇总对象的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!