业务中需要将一组数据分类后收集总和,原本可以使用Collectors.summingInt(),但是我们的数据源是BigDecimal类型的,而Java8原生只提供了summingInt、summingLong、summingDouble三种基础类型的方法。
于是就自己动手丰衣足食吧。。
自定义工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
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; } } |
自定义函数式接口
1
2
3
4
|
@FunctionalInterface public interface ToBigDecimalFunction<T> { BigDecimal applyAsInt(T value); } |
测试入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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 |
补充:Collectors扩展接口 实现BigDecimal的相加
第一步
创建ToBigDecimalFunction接口
1
2
3
4
5
|
import java.math.BigDecimal; @FunctionalInterface public interface ToBigDecimalFunction<T> { BigDecimal applyAsBigDecimal(T value); } |
第二步
创建工具类 实现接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
import java.math.BigDecimal; import java.util.Collections; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class CollectorsUtil { static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet(); private CollectorsUtil() { } @SuppressWarnings ( "unchecked" ) private static <I, R> Function<I, R> castingIdentity() { return i -> (R) i; } /** * Simple implementation class for {@code Collector}. * * @param <T> * the type of elements to be collected * @param <R> * the type of the result */ 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; 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; } } public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) { return new CollectorImpl<>(() -> new BigDecimal[ 1 ], (a, t) -> { if (a[ 0 ] == null ) { a[ 0 ] = BigDecimal.ZERO; } a[ 0 ] = a[ 0 ].add(mapper.applyAsBigDecimal(t)); }, (a, b) -> { a[ 0 ] = a[ 0 ].add(b[ 0 ]); return a; }, a -> a[ 0 ], CH_NOID); } } |
使用测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import com.example.javademo.JavaDemoApplicationTests; import com.example.javademo.pojo.Student; import com.example.javademo.utils.DataUtils; import org.junit.Test; import java.math.BigDecimal; import java.util.stream.Collectors; public class TestBigDecimal extends JavaDemoApplicationTests { @Test public void testGroupByAfterBigdecimal(){ /* 自定义实现对分组后的集合,属性为bigdecmal进行相加 */ System.out.println(DataUtils.getData().stream().collect(Collectors.groupingBy(Student::getSchool,CollectorsUtil.summingBigDecimal(Student::getMoney)))); //归约造作 BigDecimal reduce = DataUtils.getData().stream().map(Student::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add); System.out.println(reduce); int sum = DataUtils.getData().stream().mapToInt(Student::getAge).sum(); System.out.println(sum); } } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。
原文链接:https://jaemon.blog.csdn.net/article/details/103405970