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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

带对象属性的:
//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);
}
  • 1
  • 2
  • 3
  • 4
  • 5

新建工具类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);
    }
}
  • 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
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

实体类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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
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));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
//单条件筛选
//按照性别分组求分数总和
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));
  • 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

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);
}
  • 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
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

}

  • 1
posted @ 2022-08-25 09:29  甜菜波波  阅读(1146)  评论(0编辑  收藏  举报