业务中需要将一组数据分类后收集总和,原本可以使用Collectors.summingInt(),但是我们的数据源是BigDecimal类型的,而Java8原生只提供了summingInt、summingLong、summingDouble三种基础类型的方法。于是就自己动手丰衣足食吧。。
自定义工具类
public class MyCollectors {
    private MyCollectors() {
    }
//    public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(Function<? super T, BigDecimal> mapper) {}
    // BigDecimal 类型的集合求和
    public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new BigDecimal[] { BigDecimal.ZERO },
                (a, t) -> a[0] = a[0].add(mapper.applyAsInt(t)),
                (a, b) -> {
                    a[0] = a[0].add(b[0]);
                    return a;
                },
                a -> a[0],
                Collections.emptySet()
        );
    }
    static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
        // 创建一个计算用的容器
        private final Supplier<A> supplier;
        // 计算逻辑
        private final BiConsumer<A, T> accumulator;
        // 合并逻辑
        private final BinaryOperator<A> combiner;
        // 返回最终计算值
        private final Function<A, R> finisher;
        // 空Set
        private final Set<Characteristics> characteristics;
        CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner,
                      Function<A, R> finisher, Set<Characteristics> characteristics) {
            this.supplier = supplier;
            this.accumulator = accumulator;
            this.combiner = combiner;
            this.finisher = finisher;
            this.characteristics = characteristics;
        }
        CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner,
                      Set<Characteristics> characteristics) {
            this(supplier, accumulator, combiner, castingIdentity(), characteristics);
        }
        @Override
        public BiConsumer<A, T> accumulator() {
            return accumulator;
        }
        @Override
        public Supplier<A> supplier() {
            return supplier;
        }
        @Override
        public BinaryOperator<A> combiner() {
            return combiner;
        }
        @Override
        public Function<A, R> finisher() {
            return finisher;
        }
        @Override
        public Set<Characteristics> characteristics() {
            return characteristics;
        }
    }
    @SuppressWarnings("unchecked")
    private static <I, R> Function<I, R> castingIdentity() {
        return i -> (R) i;
    }
}
自定义函数式接口
@FunctionalInterface
public interface ToBigDecimalFunction<T> {
BigDecimal applyAsInt(T value);
}
测试入口
public class AnswerApp {
  public static void main(String[] args) {
        List<BigDecimal> list = Lists.newArrayList();
        for (int i = 0; i < 24; i++) {
            list.add(BigDecimal.valueOf(i + 10.2121543));
        }
        // 方式1
        BigDecimal sum = list.stream().collect(MyCollectors.summingBigDecimal(e -> e));
        System.out.println(sum.doubleValue());
        // 方式2
        Optional<BigDecimal> reduce = list.stream().reduce(BigDecimal::add);
        System.out.println(reduce.orElse(BigDecimal.valueOf(0)));
  }        
}
// OUTPUT: 521.0917032
参考地址
- Java8中Collectors求和功能的自定义扩展
 
                










