使用Stream汇总计算泛型实体Collection的BigDecimal总金额

//使用示例1 计算总包费用
BigDecimal packFee = schemes.stream().collect(Collectors.collectingAndThen(
                    SchemeDataUtilService.getContAmtDtoSupplier(DiscountScheme::getDiscountAmount),
                    a -> a.getAmt().multiply(rate).divide(BigDecimal.valueOf(100), 4, BigDecimal.ROUND_DOWN)));

//使用示例2 分组计算总金额
Collector> discountSchemeMapCollector = Collectors.groupingBy(DiscountScheme::getPrdChannelCode,
                getContAmtDtoSupplier(DiscountScheme::getDiscountAmount)
        );

Map collectAmt = schemes.stream().parallel().collect(discountSchemeMapCollector);




/**
     * 计算T的BigDecimal类型总金额和size,汇总在ContAmtDto中
     * @param converter 泛型实体的BigDecimal字段取值方法
     * @param  泛型实体
     * @return ContAmtDto 汇总结果存储DTO
     */
    public static  Collector getContAmtDtoSupplier(Function converter) {
        return Collector.of(() -> new ContAmtDto(),
                (a, t) -> {
                    if (null == a) {
                        a = new ContAmtDto().setAmt(BigDecimal.ZERO).setCount(0);
                    }
                    a.setAmt(a.getAmt().add(Optional.of(converter.apply(t)).orElse(BigDecimal.ZERO)));
                    a.setCount(a.getCount() + 1);
                },
                (a, b) -> {
                    a.setAmt(a.getAmt().add(b.getAmt()));
                    a.setCount(a.getCount()+b.getCount());
                    return a;
                }, a -> a, Collector.Characteristics.UNORDERED);
    }
    
    
/**
 * 以条数和金额汇总的DTO
 */
@Data
@Accessors(chain = true)
public class ContAmtDto {

    //需要设置初始值
    private  Integer count=0;

    //需要设置初始值
    private  BigDecimal amt=BigDecimal.ZERO;


}

你可能感兴趣的:(stream)