将对象分组以创建扩展对象列表

时间:2019-06-20 20:09:18

标签: java lambda java-8 java-stream

我有数据库中的这些示例记录,这是按查询分组的结果:

[
 {
   "name": "Troy",
   "acct": 1123,
   "type": " Savings",
   "total": 50
 },
 {
   "name": "Larry",
   "acct": 4233,
   "type": " Savings",
   "total": 200
 },
 {
   "name": "Troy",
   "acct": 1123,
   "type": " Current",
   "total": 120
 },
 {
   "name": "Larry",
   "acct": 4233,
   "type": " Current",
   "total": 220
 }
]

现在,我需要创建一个如下所示的报告:

[
 {
   "name": "Troy",
   "acct": 1123,
   "totalSavings": 50,
   "totalCurrent": 120
 },
 {
   "name": "Larry",
   "acct": 4233,
   "totalSavings": 200,
   "totalCurrent": 220
 }
]

public class DbTrans {
    private String name;
    private String acct;
    private String type;
    private double total;

// getters and setters
...
}

我已经尝试使用如下所示的一些lambda技术,但我仍未达到我想要的解决方案。

 Map<String, List<DbTrans>> collect = transList.stream().collect(
          Collectors.groupingBy(f -> f.getType()));

2 个答案:

答案 0 :(得分:5)

首先,响应Dto与请求Dto不同,我建议创建一个名为它的新Response类:

public class DbTransResponse {
    private String name;
    private String acct;
    private double totalSavings;
    private double totalCurrent;
    // getters and setters
}

然后结果可以像这样:

List<DbTransResponse> result = transList.stream()
        .collect(Collectors.groupingBy(DbTrans::getAcct))
        .values().stream()
        .map(trans -> new DbTransResponse(
                trans.get(0).getName(),
                trans.get(0).getAcct(),
                trans.get(0).getTotal(),
                trans.get(1).getTotal()
        )).collect(Collectors.toList());

我认为该列表应包含每个名称的两个条目,以便您可以从第一个条目totalSavings获得trans.get(0).getTotal(),从第二个totalCurrent获得trans.get(1).getTotal()。 / p>

例如,如果不确定是否可以使用条件填充对象,则可以检查是否有两个元素(如果未设置默认值)。


Ideone demo

输出

DbTransResponse{name='Larry', acct='4233', totalSavings=200.0, totalCurrent=220.0}
DbTransResponse{name='Troy', acct='1123', totalSavings=50.0, totalCurrent=120.0}

答案 1 :(得分:2)

您可以为此目的使用Collectors::toMap(只需执行一次collect操作)

 Map<Integer, DbTransResponse> collect = transList.stream()
            .collect(Collectors.toMap(DbTrans::getAcct, 
                                      DbTransResponse::new, 
                                      DbTransResponse::merge));

 Collection<DbTransResponse> result = collect.values();

这是DbTransResponse类中的合并方法

static DbTransResponse merge(DbTransResponse r1, DbTransResponse r2) {
        return new DbTransResponse(
                r1.name, r1.acct,
                r1.totalSavings + r2.totalSavings,
                r1.totalCurrent + r2.totalCurrent
        );
    }

DbTransResponse类的其他构造函数,尽管您可以将此逻辑移至方法

DbTransResponse(DbTrans dbTrans) {
   this.name = dbTrans.getName();
   this.acct = dbTrans.getAcct();
   this.totalSavings = "Savings".equals(dbTrans.getType()) ? dbTrans.getTotal() : 0;
   this.totalCurrent = "Current".equals(dbTrans.getType()) ? dbTrans.getTotal() : 0;

}

demo