使用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<DiscountScheme, ?, Map<String, ContAmtDto>> discountSchemeMapCollector = Collectors.groupingBy(DiscountScheme::getPrdChannelCode,
                getContAmtDtoSupplier(DiscountScheme::getDiscountAmount)
        );

Map<String, ContAmtDto> collectAmt = schemes.stream().parallel().collect(discountSchemeMapCollector);




/**
     * 计算T的BigDecimal类型总金额和size,汇总在ContAmtDto中
     * @param converter 泛型实体的BigDecimal字段取值方法
     * @param <T> 泛型实体
     * @return ContAmtDto 汇总结果存储DTO
     */
    public static <T> Collector<T, ContAmtDto, ContAmtDto> getContAmtDtoSupplier(Function<T,BigDecimal> 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;


}
相关文章
相关标签/搜索