業務中須要將一組數據分類後收集總和,本來能夠使用Collectors.summingInt()
,可是咱們的數據源是BigDecimal類型的,而Java8原生只提供了summingInt、summingLong、summingDouble三種基礎類型的方法。因而就本身動手豐衣足食吧。。app
指望目標:this
Map<String, BigDecimal> result = Arrays.stream(records).parallel().collect(Collectors.groupingBy( Record::getType, CollectorsUtil.summingBigDecimal(Record::getAmount)));
1. 依葫蘆
先分析一下Collectors.summingInt()
方法code
public static <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper) { return new CollectorImpl<>( () -> new int[1], (a, t) -> { a[0] += mapper.applyAsInt(t); }, (a, b) -> { a[0] += b[0]; return a; }, a -> a[0], CH_NOID); }
該方法接受ToIntFunction<? super T>
類型的參數,返回CollectorImpl
類型的實例化對象。CollectorImpl
是Collector
接口的惟一實現類對象
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
的構造器參數,可知summingInt()
方法是這樣的接口
arg[0]建立一個計算用的容器: () -> new int[1]
arg[1]爲計算邏輯: (a, t) -> { a[0] += mapper.applyAsInt(t); }
arg[2]爲合併邏輯: (a, b) -> { a[0] += b[0]; return a; }
arg[3]爲返回最終計算值: a -> a[0]
arg[4]爲空Set(不知道幹什麼用。。): Collections.emptySet()
事務
2. 畫瓢
很天然的,BigDecimal的就是這樣了ip
public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(Function<? super T, BigDecimal> mapper) { return new CollectorImpl<>(() -> new BigDecimal[] { BigDecimal.ZERO }, (a, t) -> { a[0] = a[0].add(mapper.apply(t)); }, (a, b) -> { a[0] = a[0].add(b[0]); return a; }, a -> a[0], CH_NOID); }