//使用示例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; }