Java stream groupingBy and sum multiple fields(Java流groupingBy并对多个字段求和)
问题描述
这是我的列表 fooList
Here is my List fooList
class Foo {
private String name;
private int code;
private int account;
private int time;
private String others;
... constructor, getters & setters
}
例如(帐户的所有值都已设置为1)
e.g.(all the value of account has been set to 1)
new Foo(First, 200, 1, 400, other1),
new Foo(First, 200, 1, 300, other1),
new Foo(First, 201, 1, 10, other1),
new Foo(Second, 400, 1, 20, other2),
new Foo(Second, 400, 1, 40, other2),
new Foo(Third, 100, 1, 200, other3),
new Foo(Third, 101, 1, 900, other3)
我想通过将名称"分组来转换这些值.和代码",计算数字,并对时间"求和,例如
I want to transform these values by grouping "name" and "code", accounting for the number, and summing the "time", e.g.
new Foo(First, 200, 2, 700, other1),
new Foo(First, 201, 1, 10, other1),
new Foo(Second, 400, 2, 60, other2),
new Foo(Third, 100, 1, 200, other3),
new Foo(Third, 101, 1, 900, other3)
我知道我应该使用这样的流:
I know that I should use a stream like this:
Map<String, List<Foo>> map = fooList.stream().collect(groupingBy(Foo::getName()));
但我如何按代码对它们进行分组,然后进行会计和汇总工作?
but how can I group them by code then do the accounting and summing job?
另外,如果我想计算平均时间怎么办?例如
Also, what if I want to calculate the average time? e.g.
new Foo(First, 200, 2, 350, other1),
new Foo(First, 201, 1, 10, other1),
new Foo(Second, 400, 2, 30, other2),
new Foo(Third, 100, 1, 200, other3),
new Foo(Third, 101, 1, 900, other3)
我可以同时使用 summingInt(Foo::getAccount)
和 averagingInt(Foo::getTime)
吗?
Can I use both of summingInt(Foo::getAccount)
and averagingInt(Foo::getTime)
instead?
推荐答案
一种解决方法是处理 grouping
键为 List
并在映射回对象时进行转换输入.
A workaround could be to deal with grouping
with key as List
and casting while mapping back to object type.
List<Foo> result = fooList.stream()
.collect(Collectors.groupingBy(foo ->
Arrays.asList(foo.getName(), foo.getCode(), foo.getAccount()),
Collectors.summingInt(Foo::getTime)))
.entrySet().stream()
.map(entry -> new Foo((String) entry.getKey().get(0),
(Integer) entry.getKey().get(1),
entry.getValue(),
(Integer) entry.getKey().get(2)))
.collect(Collectors.toList());
更简洁的方法是公开用于合并功能的 API 并执行 toMap
.
Cleaner way would be to expose APIs for merge function and performing a toMap
.
编辑:toMap
的简化如下所示
List<Foo> result = new ArrayList<>(fooList.stream()
.collect(Collectors.toMap(foo -> Arrays.asList(foo.getName(), foo.getCode()),
Function.identity(), Foo::aggregateTime))
.values());
其中 aggregateTime
是 Foo
中的静态方法,例如:
where the aggregateTime
is a static method within Foo
such as this :
static Foo aggregateTime(Foo initial, Foo incoming) {
return new Foo(incoming.getName(), incoming.getCode(),
incoming.getAccount(), initial.getTime() + incoming.getTime());
}
这篇关于Java流groupingBy并对多个字段求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Java流groupingBy并对多个字段求和
基础教程推荐
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 降序排序:Java Map 2022-01-01