简体   繁体   English

Java GroupBy 乘以总和

[英]Java GroupBy multiple with Sum

I'm trying to make group by like in mySQL, I have multiple columns (properties) and I must group by two fields ( socio and idSolicitudEgreso ) and sum another one ( montoPago ).我试图让group by就像在MySQL中,我有多个列(属性),我必须利用两个场组( socioidSolicitudEgreso ),总结另一个( montoPago )。 I did:我做了:

Map<String, Map<String, Integer>> mymap = santa.stream()
        .collect(Collectors.groupingBy(Santander::getPanSocio,
                 Collectors.groupingBy(Santander::getPanIdsolicitudegreso,
                 Collectors.summingInt(Santander::getPanMontopago))));

mymap.forEach((key, value) -> System.out.println(key + ":" + value));

My class object is:我的类对象是:

public class Santander {

    private String panRutbeneficiario;
    private String panNombrebeneficiario;
    private String panEmailbeneficiario;
    private String panMetodopago;
    private String panCodigobancoabono;
    private String panTipocuentaabono;
    private String panNumcuentaabono;
    private String panFechapago;
    private String panCampobanco1;
    private String panCampobanco2;
    private int panMontopago;
    private String panTipocuentacargodet;
    private String panNumcuentacargodet;
    private String panCodigosucursal;
    private String panReferenciacliente;
    private String panRetencionfactura;
    private String panAbonovalesvistalinea;
    private String panCantidaddocumentos;
    private String panSocio;
    private String panIdsolicitudegreso;
}

I getting this result with this code:我用这个代码得到这个结果:

BANCO DEL ESTADO:{35113=3026882} BANCO DEL ESTADO:{35113=3026882}

As you can see I get the group very well, ( socio , id and sum as well), but I need to get all the objects or list of object.正如你所看到的,我很好地得到了组,( socio , idsum ),但我需要获取所有对象或对象列表。 I just get 3 of 20 fields.我只得到 20 个字段中的 3 个。 What change I must do in my Java stream code to get the list of objects (grouped)?我必须在 Java 流代码中进行哪些更改才能获取对象列表(分组)? Please?请?

Thanks谢谢

PS: the output I expect is: PS:我期望的输出是:

{  panRutbeneficiario=146174558, panNombrebeneficiario=No Definido,
   panEmailbeneficiario=, panMetodopago=CAT_CSH_TRANSFER, panCodigobancoabono=12,
   panTipocuentaabono=Ahorro, panNumcuentaabono=8275301, panFechapago=2020-07-30,
   panCampobanco1=, panCampobanco2=, panMontopago=111960,
   panTipocuentacargodet=CAT_CSH_CCTE, panNumcuentacargodet=null,
   panCodigosucursal=, panReferenciacliente=, panRetencionfactura=,
   panAbonovalesvistalinea=null, panCantidaddocumentos=null, 
   panSocio=BANCO DEL ESTADO, panIdsolicitudegreso=35113
}

You may need to prepare an object to hold the grouping result for example:您可能需要准备一个对象来保存分组结果,例如:

public class Summary {
    private final String panSocio;
    private final String panSolicitude;
    private final int total;

    public Summary(String socio, String solicitude, int total) {
        this.panSocio = socio;
        this.panSolicitude = solicitude;
        this.total = total;
    }

    public String getPanSocio() { return this.panSocio; }
    public String getPanSolicitude() { return this.panSolicitude; }
    public int getTotal() { return this.total; }

    public String toString() {
        return String.format("{ socio=\"%s\", solicitude=\"%s\", total=%d}%n",
                panSocio, panSolicitude, total);
    }
}

Then it is possible to iterate over the entries of mymap , use flatMap to transform the entries of the inner map into Stream<Summary> therefore collecting into the list of Summary objects (sorted if necessary):然后可以迭代mymap的条目,使用flatMap将内部映射的条目转换为Stream<Summary>从而收集到Summary对象列表中(如有必要,进行排序):

List<Summary> remap = mymap.entrySet()
        .stream()
        .flatMap(e -> e.getValue().entrySet()  // e.getKey() -> panSocio
                       .stream()               // ee.getKey() -> solicitude, ee.getValue() -> total
                       .map(ee -> new Summary(e.getKey(), ee.getKey(), ee.getValue()))
        )
        .sorted(Comparator.comparing(Summary::getPanSocio)
                          .thenComparing(Summary::getPanSolicitude))
        .collect(Collectors.toList());

Update更新

Of course, it is possibe to reuse existing Santander class to collect the results providing that Santander has a constructor or builder allowing to populate at least the three relevant fields panSocio , panSolicitude , panMontopago :当然,如果Santander具有允许填充至少三个相关字段panSociopanSolicitudepanMontopago的构造函数或构建器,则可以重用现有的Santander类来收集结果:

List<Santander> grouped = mymap.entrySet()
        .stream()
        .flatMap(e -> e.getValue().entrySet()  // e.getKey() -> panSocio
                       .stream()               // ee.getKey() -> solicitude, ee.getValue() -> total
                       .map(ee -> new Santander(e.getKey(), ee.getKey(), ee.getValue())) // the rest of the fields set to some default values
        )
        .collect(Collectors.toList());

However, the rest of Santander fields will be undefined / default upon applying summarizingInt collector by Santander::getMontopago .但是,在Santander::getMontopago应用summarizingInt收集器后,其余的Santander字段将是未定义/默认的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM