java分组求和实例,Java流分组通过对多个字段求和

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

}

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

Can I use both of summingInt(Foo::getAccount) and averagingInt(Foo::getTime) instead?

解决方案

A workaround could be to deal with grouping with key as List and casting while mapping back to object type.

List 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());

Cleaner way would be to expose APIs for merge function and performing a toMap.

Edit: The simplification with toMap would look like the following

List result = new ArrayList<>(fooList.stream()

.collect(Collectors.toMap(foo -> Arrays.asList(foo.getName(), foo.getCode()),

Function.identity(), Foo::aggregateTime))

.values());

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());

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值