BigDecimal 的 summing、maxBy、minBy、averaging

BigDecimal 流中无拆箱操作,故JDK无BigDecimal的summing、maxBy、minBy、averaging。

看有不少同学放展示自用的收集器、也特此展示一个自用的较热门BigDecimal收集器。

同Int、Long、Double的写法一样类似,如下:

 1 static final Set<Collector.Characteristics> CH_ID
 2             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
 3 static final Collector.Characteristics[] CH_NOID_ARRAY = CH_NOID.toArray(new Collector.Characteristics[0]);
 4 
 5 /**
 6      * Returns a {@code Collector} that produces the sum of a BigDecimal-valued
 7      * function applied to the input elements.  If no elements are present,
 8      * the result is 0.
 9      *
10      * @param <T>    the type of the input elements
11      * @param mapper a function extracting the property to be summed
12      * @return a {@code Collector} that produces the sum of a derived property
13      */
14     public static <T> Collector<T, ?, BigDecimal>
15     summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
16         return Collectors.reducing(
17                 BigDecimal.ZERO,
18                 mapper::applyAsBigDecimal,
19                 BigDecimal::add
20         );
21     }
22 
23     public static <T> Collector<T, ?, BigDecimal>
24     maxBy(ToBigDecimalFunction<? super T> mapper) {
25         // 多个流combiner注意逻辑默认值
26         return Collectors.reducing(
27                 BigDecimal.valueOf(Long.MIN_VALUE),
28                 mapper::applyAsBigDecimal,
29                 BigDecimal::max
30         );
31     }
32 
33     public static <T> Collector<T, ?, BigDecimal>
34     minBy(ToBigDecimalFunction<? super T> mapper) {
35         // 多个流combiner注意逻辑默认值
36         return Collectors.reducing(
37                 BigDecimal.valueOf(Long.MAX_VALUE),
38                 mapper::applyAsBigDecimal,
39                 BigDecimal::min
40         );
41     }
42 
43     public static <T> Collector<T, ?, BigDecimal>
44     averagingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
45         return Collector.of(
46                 () -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
47                 (r, t) -> {
48                     r[0] = r[0].add(mapper.applyAsBigDecimal(t));
49                     r[1] = BigDecimal.ONE.add(r[1]);
50                 },
51                 (left, right) -> {
52                     left[0] = left[0].add(right[0]);
53                     left[1] = left[1].add(right[1]);
54                     return left;
55                 },
56                 r -> BigDecimal.ZERO.compareTo(r[1]) == 0 ?
57                         BigDecimal.ZERO : r[0].divide(r[1], 2, RoundingMode.HALF_UP),
58                 CH_NOID_ARRAY
59         );
60     }
61 
62     public static <T> Collector<T, ?, BigDecimal>
63     averagingBigDecimal(ToBigDecimalFunction<? super T> mapper,
64                         int scale,
65                         RoundingMode roundingMode) {
66         return Collector.of(
67                 () -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
68                 (r, t) -> {
69                     r[0] = r[0].add(mapper.applyAsBigDecimal(t));
70                     r[1] = BigDecimal.ONE.add(r[1]);
71                 },
72                 (left, right) -> {
73                     left[0] = left[0].add(right[0]);
74                     left[1] = left[1].add(right[1]);
75                     return left;
76                 },
77                 r -> BigDecimal.ZERO.compareTo(r[1]) == 0 ?
78                         BigDecimal.ZERO : r[0].divide(r[1], scale, roundingMode),
79                 CH_NOID_ARRAY
80         );
81     }

max、min来个默认值?Zero | 也可以自己加个入参作为DefaultValue。

 1 public static <T> Collector<T, ?, BigDecimal>
 2     maxByDefaultZero(ToBigDecimalFunction<? super T> mapper) {
 3         // 不推荐,建议在进行收集前count,多个流combiner注意逻辑默认值
 4         return Collector.of(
 5                 () -> new BigDecimal[]{new BigDecimal(Long.MIN_VALUE), BigDecimal.ZERO},
 6                 (r, t) -> {
 7                     r[0] = r[0].max(mapper.applyAsBigDecimal(t));
 8                     r[1] = BigDecimal.ONE.add(r[1]);
 9                 },
10                 (left, right) -> {
11                     left[0] = left[0].max(right[0]);
12                     left[1] = left[1].add(right[1]);
13                     return left;
14                 },
15                 r -> BigDecimal.ZERO.compareTo(r[1]) == 0 ? BigDecimal.ZERO : r[0],
16                 CH_NOID_ARRAY
17         );
18     }
19 
20     public static <T> Collector<T, ?, BigDecimal>
21     minByDefaultZero(ToBigDecimalFunction<? super T> mapper) {
22         // 不推荐,建议在进行收集前count,多个流combiner注意逻辑默认值
23         return Collector.of(
24                 () -> new BigDecimal[]{new BigDecimal(Long.MAX_VALUE), BigDecimal.ZERO},
25                 (r, t) -> {
26                     r[0] = r[0].min(mapper.applyAsBigDecimal(t));
27                     r[1] = BigDecimal.ONE.add(r[1]);
28                 },
29                 (left, right) -> {
30                     left[0] = left[0].min(right[0]);
31                     left[1] = left[1].add(right[1]);
32                     return left;
33                 },
34                 r -> BigDecimal.ZERO.compareTo(r[1]) == 0 ? BigDecimal.ZERO : r[0],
35                 CH_NOID_ARRAY
36         );
37     }

需要更多自定义收集器?看到留言后斟酌加一篇。

posted @ 2021-07-22 14:16  河图书卦  阅读(462)  评论(0编辑  收藏  举报