Java流groupingBy并对多个字段求和

标签 java lambda java-stream grouping

这是我的列表 fooList

class Foo {
    private String name;
    private int code;
    private int account;
    private int time;
    private String others;

    ... constructor, getters & setters
}

例如(账户的所有值已设置为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)

我想通过对“名称”和“代码”进行分组、计算数量并对“时间”求和来转换这些值,例如

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)

我知道我应该使用这样的流:

Map<String, List<Foo>> map = fooList.stream().collect(groupingBy(Foo::getName()));

但是我如何按代码将它们分组然后进行会计和求和工作?


另外,如果我想计算平均时间怎么办?例如

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) 吗?

最佳答案

解决方法可能是使用键作为 List 处理分组,并在映射回对象类型时进行转换。

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


编辑:使用 toMap 进行的简化如下所示

List<Foo> result = new ArrayList<>(fooList.stream()
        .collect(Collectors.toMap(foo -> Arrays.asList(foo.getName(), foo.getCode()),
                Function.identity(), Foo::aggregateTime))
        .values());

其中 aggregateTimeFoo 中的静态方法,如下所示:

static Foo aggregateTime(Foo initial, Foo incoming) {
    return new Foo(incoming.getName(), incoming.getCode(),
            incoming.getAccount(), initial.getTime() + incoming.getTime());
}

关于Java流groupingBy并对多个字段求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62286182/

相关文章:

java - 为什么带符号的右移会带来 1 而不是只在最重要的位置保留 1?

c# - delegate 关键字与 lambda 表示法

c# - 使用表达式树创建完全动态的 where 子句并在 IQueryable 上执行

java - 按范围日期分组

java - 我可以按元素的类过滤 Stream<T> 并一步获得 Stream<U> 吗?

java - 将 jar 文件安装到 Tomcat Web 应用程序

java - fragment 和 fragmentActivity 的 Android 问题

java - 什么是 org.eclipse.swt.widgets.Table;相当于 jTable1.setValueAt?

asp.net - 如何在 mvc3 中创建自定义过滤器工具栏 html 帮助器

dictionary - Java 8 将 Map<Department, List<Person>> 转换为 Map<Department, List<String>>