List集合中的对象值是BigDecimal对所有对象都需要相同的类型BigDecimal求和类型的属性,找不到现成的工具类,可以自己定义一个。
1.定义工具类
package com.kakarote.core.utils; import lombok.Data; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.math.MathContext; import java.util.*; 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; import java.util.stream.Collectors; /** * JAVA8 分组求和使用方法 */ public class CollectorsUtils { private static final Set<Collector.Characteristics> CHARACTERISTICS = Collections.emptySet(); private CollectorsUtils() { } @SuppressWarnings("unchecked") private static <I, R> Function<I, R> check() { return i -> (R) i; } @SuppressWarnings("hiding") 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, check(), characteristics); } @Override public Supplier<A> supplier() { return supplier; } @Override public BiConsumer<A, T> accumulator() { return accumulator; } @Override public BinaryOperator<A> combiner() { return combiner; } @Override public Function<A, R> finisher() { return finisher; } @Override public Set<Characteristics> characteristics() { return characteristics; } } /** * 求和方法 * @param mapper * @param <T> * @return */ public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) { return new CollectorImpl<>( () -> new BigDecimal[]{new BigDecimal(0)}, (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t), MathContext.DECIMAL32); }, (a, b) -> { a[0] = a[0].add(b[0], MathContext.DECIMAL32); return a; }, a -> a[0], CHARACTERISTICS ); } /** * 寻求最大值,这里最小值MIN如果某些数据范围超过100亿,作为初始条件判断值,可根据需要替换 Long.MIN_VALUE 或者 Double.MIN_VALUE * @param mapper * @param <T> * @return */ public static <T> Collector<T, ?, BigDecimal> maxBy(ToBigDecimalFunction<? super T> mapper) { return new CollectorImpl<>( () -> new BigDecimal[]{new BigDecimal(Integer.MIN_VALUE)}, (a, t) -> { a[0] = a[0].max(mapper.applyAsBigDecimal(t)); }, (a, b) -> { a[0] = a[0].max(b[0]); return a; }, a -> a[0], CHARACTERISTICS ); } /** * 求最小值,这里最大值MAX如果某些数据范围超过100亿,作为初始条件判断值,可根据需要替换 Long.MAX_VALUE 或者 Double.MAX_VALUE * @param mapper * @param <T> * @return */ public static <T> Collector<T, ?, BigDecimal> minBy(ToBigDecimalFunction<? super T> mapper) { return new CollectorImpl<>( () -> new BigDecimal[]{new BigDecimal(Integer.MAX_VALUE)}, (a, t) -> { a[0] = a[0].min(mapper.applyAsBigDecimal(t)); }, (a, b) -> { a[0] = a[0].min(b[0]); return a; }, a -> a[0], CHARACTERISTICS ); } /** * 求平均,并且保留小数,返回平均值 * @param mapper * @param newScale * @param roundingMode * @param <T> * @return */ public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(ToBiDecimalFunction<? super T> mapper,
int newScale, int roundingMode) {
return new CollectorImpl<>(
() -> new BigDecimal[]{new BigDecimal(0), new BigDecimal(0)},
(a, t) -> {
a[0] = a[0].add(mapper.applyAsBigDecimal(t));
a[1] = a[1].add(BigDecimal.ONE);
},
(a, b) -> {
a[0] = a[0].min(b[0]);
return a;
},
a -> a[0].divide(a[1], MathContext.DECIMAL32).setScale(newScale, roundingMode), CHARACTERISTICS
);
}
// 自定义函数
@FunctionalInterface
interface ToBigDecimalFunction<T> {
BigDecimal applyAsBigDecimal(T t);
}
}
2.定义实体类
@Data
@Accessors(chain = true) // 开启链式编程
static class People{
Long id;
Integer sex;
BigDecimal money;
}
3.测试
public static void main(String[] args) {
List<People> list = new ArrayList<People>();
list.add(new People().setId(1l).setSex(1).setMoney(BigDecimal.ONE));
list.add(new People().setId(2l).setSex(1).setMoney(BigDecimal.TEN));
list.add(new People().setId(3l).setSex(0).setMoney(BigDecimal.ZERO));
list.add(new People().setId(4l).setSex(0).setMoney(BigDecimal.TEN));
list.add(new People().setId(5l).setSex(1).setMoney(BigDecimal.valueOf(5)));
BigDecimal sum = list.stream().collect(CollectorsUtils.summingBigDecimal(People::getMoney));
System.out.println("求和:" + sum);
Map<Integer, BigDecimal> collect = list.stream().collect(Collectors.groupingBy(People::getSex, CollectorsUtils.summingBigDecimal(People::getMoney)));
System.out.println("分组求和:" + collect);
}
4.结果
求和:26
分组求和:{0=10, 1=16}
java8lamdba表达式list集合的BigDecimal求和操作