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 }
需要更多自定义收集器?看到留言后斟酌加一篇。