Java8 对list集合中的bigdecimal进行分组求和,均值,最大值,最小值

需求中对数值进行求和的非常多,但java8对bigdecimal求和没有封装

通常求和我们都这么做:

    public static void main(String[] args) {
        List<BigDecimal> list = new ArrayList<>();
        list.add(BigDecimal.valueOf(1.1));
        list.add(BigDecimal.valueOf(1.2));
        list.add(BigDecimal.valueOf(1.3));
        list.add(BigDecimal.valueOf(1.4));
 
        BigDecimal decimal = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println(decimal);
    }

带对象属性的:
//BigDecimal
BigDecimal total = list.stream().map(ReturnMoney::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

可不可以类似double求和
//mapToDouble,mapToInt,mapToLong
Double total = list.stream().mapToDouble(ReturnMoney::getAmount()).sum()//和;.max()//最大;.min()//最小;.average()//平均值

下面就对bigdecimal运算进行封装:

新建接口ToBigDecimalFunction

@FunctionalInterface
public interface ToBigDecimalFunction<T> {
    BigDecimal applyAsBigDecimal(T value);
}

新建工具类CollectorsUtil

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;
    }

    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[]{BigDecimal.ZERO},
                (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t)); },
                (a, b) -> { a[0] = a[0].add(b[0]) ; return a; },
                a -> a[0], CH_NOID);
    }

    //求最大值
    public static <T> Collector<T, ?, BigDecimal> maxBy(ToBigDecimalFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new BigDecimal[]{new BigDecimal(Long.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], CH_NOID);
    }

    //求最小值
    public static <T> Collector<T, ?, BigDecimal> minBy(ToBigDecimalFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new BigDecimal[]{new BigDecimal(Long.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], CH_NOID);
    }

    //求平均值
    public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(ToBigDecimalFunction<? super T> mapper, int newScale, int roundingMode) {
        return new CollectorImpl<>(
                () -> new BigDecimal[]{BigDecimal.ZERO,BigDecimal.ZERO},
                (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t)); a[1] = a[1].add(BigDecimal.ONE); },
                (a, b) -> { a[0] = a[0].add(b[0]) ; return a; },
                a -> a[0].divide(a[1],BigDecimal.ROUND_HALF_UP).setScale(newScale, roundingMode), CH_NOID);
    }
}

实体类Person

@Data
class Person{
    private String sex;
    private Integer age;
    private BigDecimal score;

    public Person(String sex, Integer age, BigDecimal score) {
        this.sex = sex;
        this.age = age;
        this.score = score;
    }
}

List<Person> list = new ArrayList<>();
list.add(new Person("男",18,new BigDecimal(100)));
list.add(new Person("男",19,new BigDecimal(90)));
list.add(new Person("女",20,new BigDecimal(80)));
list.add(new Person("女",20,new BigDecimal(70)));
list.add(new Person("女",20,null));

//单条件筛选
//按照性别分组求分数总和
Map<String, BigDecimal> scoreCount = list.stream()
        .filter(t -> t.getScore() != null)
        .collect(Collectors.groupingBy(Person::getSex, CollectorsUtil.summingBigDecimal(Person::getScore)));
System.out.println("----按照性别分组求分数总和----");
scoreCount.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));

//按照性别求分数平均值
Map<String, BigDecimal> scoreAvg = list.stream()
        .filter(t -> t.getScore() != null)
        .collect(Collectors.groupingBy(Person::getSex, CollectorsUtil.averagingBigDecimal(Person::getScore,2)));
System.out.println("----按照性别求分数平均值----");
scoreAvg.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));


//多条件筛选
//多条件筛选分组属性
private static String fetchGroupKey(Person p) {
    return p.getAge() + "#" + p.getSex();
}

//按照性别年龄分组求分数总和
Map<String, BigDecimal> ageScoreCount = list.stream()
        .filter(t -> t.getScore() != null)
        .collect(Collectors.groupingBy(p -> fetchGroupKey(p), CollectorsUtil.summingBigDecimal(Person::getScore)));
System.out.println("----按照性别年龄分组求分数总和----");
ageScoreCount.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));

//按照性别年龄分组求分数平均值
Map<String, BigDecimal> ageScoreAvg = list.stream()
        .filter(t -> t.getScore() != null)
        .collect(Collectors.groupingBy(p -> fetchGroupKey(p), CollectorsUtil.averagingBigDecimal(Person::getScore, 2)));
System.out.println("----按照性别年龄分组求分数平均值----");
ageScoreAvg.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));


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;
}

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[]{BigDecimal.ZERO},
            (a, t) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:BigDecimal.ZERO).add(ObjectUtil.isNotEmpty(mapper.applyAsBigDecimal(t))?mapper.applyAsBigDecimal(t):BigDecimal.ZERO);
            },
            (a, b) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:BigDecimal.ZERO).add((ObjectUtil.isNotNull(b[0])?b[0]:BigDecimal.ZERO)) ; return a; },
            a -> a[0], CH_NOID);
}

//求最大值
public static <T> Collector<T, ?, BigDecimal> maxBy(ToBigDecimalFunction<? super T> mapper) {
    return new CollectorImpl<>(
            () -> new BigDecimal[]{new BigDecimal(Long.MIN_VALUE)},
            (a, t) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:new BigDecimal(Long.MIN_VALUE)).max(ObjectUtil.isNotEmpty(mapper.applyAsBigDecimal(t))?mapper.applyAsBigDecimal(t):new BigDecimal(Long.MIN_VALUE)); },
            (a, b) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:BigDecimal.ZERO).max((ObjectUtil.isNotNull(b[0])?b[0]:BigDecimal.ZERO)) ; return a; },
            a -> a[0], CH_NOID);
}

//求最小值
public static <T> Collector<T, ?, BigDecimal> minBy(ToBigDecimalFunction<? super T> mapper) {
    return new CollectorImpl<>(
            () -> new BigDecimal[]{new BigDecimal(Long.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], CH_NOID);
}

//求平均值  null不计数
public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(ToBigDecimalFunction<? super T> mapper, int newScale, int roundingMode) {
    return new CollectorImpl<>(
            () -> new BigDecimal[]{BigDecimal.ZERO,BigDecimal.ZERO},
            (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t)); a[1] = a[1].add(BigDecimal.ONE); },
            (a, b) -> { a[0] = a[0].add(b[0]) ; return a; },
            a -> a[0].divide(a[1],BigDecimal.ROUND_HALF_UP).setScale(newScale, roundingMode), CH_NOID);
}
//求平均值 null计数
public static <T> Collector<T, ?, BigDecimal> averagingBigDecimalIncludsNull(ToBigDecimalFunction<? super T> mapper, int newScale, int roundingMode) {
    return new CollectorImpl<>(
            () -> new BigDecimal[]{BigDecimal.ZERO,BigDecimal.ZERO},
            (a, t) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:BigDecimal.ZERO).add(ObjectUtil.isNotEmpty(mapper.applyAsBigDecimal(t))?mapper.applyAsBigDecimal(t):BigDecimal.ZERO);
            a[1] = a[1].add(BigDecimal.ONE);
            },
            (a, b) -> { a[0] = (ObjectUtil.isNotNull(a[0])?a[0]:BigDecimal.ZERO).add((ObjectUtil.isNotNull(b[0])?b[0]:BigDecimal.ZERO)) ; return a; },
            a -> a[0].divide(a[1],BigDecimal.ROUND_HALF_UP).setScale(newScale, roundingMode), CH_NOID);
}

}


  • 0
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值