使用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;


}
相關文章
相關標籤/搜索