将集合内的元素分组相加

前言:在做报表统计的时候会经常对数据进行分组,然后相加。这里我提出四种情况

先写测试类

@Data
public class ss {

    private BigDecimal age;
    private BigDecimal money;
    private String name;

    public ss(BigDecimal age, BigDecimal money, String name) {
        this.age = age;
        this.money = money;
        this.name = name;
    }
}

工具类:

public class BigDecimalFunctionUtil {
    public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
        return new CollectorImpl<>(() -> new BigDecimal[1], (a, t) -> {
            if (a[0] == null) {
                a[0] = BigDecimal.ZERO;
            }
            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 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;
    }
    private static <I, R> Function<I, R> castingIdentity() {
        return i -> (R) i;
    }
}
@FunctionalInterface
public interface ToBigDecimalFunction<T> {
    BigDecimal applyAsBigDecimal(T value);
}

一、根据一个name字段分组,只有一个age字段相加,得到age的总和

        Map<String, BigDecimal> collect = s.stream().collect(Collectors.groupingBy(ss::getName, util.summingBigDecimal(ss::getAge)));
        BigDecimal totalAge = collect1.get("b");

二、根据一个name字段分组,money和age字段相加,分别得到money和age的总和

Map<String, List<ss>> collect = s.stream().collect(Collectors.groupingBy(ss::getName));
  List<ss> b = collect.get("b");
   BigDecimal collect1 = b.stream().collect(util.summingBigDecimal(ss::getAge)); // age的总和
   BigDecimal collect2 = b.stream().collect(util.summingBigDecimal(ss::getMoney)); // money的总和

三、根据name和age字段分组,只有一个money字段相加,得到money的总和

 *  Map<AbstractMap.SimpleEntry<String, BigDecimal>, BigDecimal> collect = s.stream().collect(Collectors.groupingBy(record -> new AbstractMap.SimpleEntry<>(record.getName(), record.getAge()), util.summingBigDecimal(ss::getMoney)));
        // 输出结果
     collect.forEach((key, totalValue) ->
                {
                 
                    System.out.println("name: " + key.getKey() + ", age: " + key.getValue() + ", Total Money: " + totalValue);
                }
        );

三、根据name和age字段分组,money和age字段相加,分别得到money和age的总和

Map<AbstractMap.SimpleEntry<String, BigDecimal>, List<ss>> collect = s.stream().collect(Collectors.groupingBy(record -> new AbstractMap.SimpleEntry<>(record.getName(), record.getAge())));
        // 输出结果
        collect.forEach((key, totalValue) ->
                {
                    BigDecimal totalMoney = totalValue.stream().collect(util.summingBigDecimal(ss::getMoney));
                    System.out.println("name: " + key.getKey() + ", age: " + key.getValue() + ", Total Money: " + totalMoney);
                }
        );

总结:其实就是几个条件分组和几个结果相加。使用到的stream流返回的结果不一样,一般不会只有一个结果列相加,会有很多,所以推荐使用先分组,再分别取每一组内的数据元素的和

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘个Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值