使用Stream API汇总对象的属性 [英] Sum attribute of object with Stream API

查看:225
本文介绍了使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆