如何对集合对象求合计,然后追加在该集合对象中

前言

在日常工作中,我们经常会遇到对一个列表的每一项求合计,然后追加到列表的最后一行。如

1

22

方案

  1. 修改该统计查询的sql,在里面追加一行合计计算。不太好的地方就是在sql有好多的函数计算,而且还要修改这个统计的sql,本来sql已经很复杂,然后再加就搞得又臭又长。
  2. 在代码中计算,这个也是比较麻烦。所以拿出来我这个方法了

之前我是这样写的,遍历集合中的每个对象,求和,将和放到新对象然后追加到集合中

private void sumDataScreening(List<IpepShipWasteData> list) {
        IpepShipWasteData data = new IpepShipWasteData();
        data.setCode("合计");
        list.stream().forEach(d->{
            data.setProvideTimes(Optional.ofNullable(data.getProvideTimes()).orElse(0) + d.getProvideTimes());
            data.setShipRubbishTransportAmount(Optional.ofNullable(data.getShipRubbishReceiveAmount()).orElse(0f) + d.getShipRubbishReceiveAmount());
            data.setShipRubbishReceiveAmount(Optional.ofNullable(data.getShipRubbishReceiveAmount()).orElse(0f) + d.getShipRubbishReceiveAmount());
            data.setShipRubbishReceiveTimes(Optional.ofNullable(data.getShipRubbishReceiveTimes()).orElse(0) + d.getShipRubbishReceiveTimes());
            data.setSewageTransportAmount(Optional.ofNullable(data.getShipRubbishReceiveAmount()).orElse(0f) + d.getShipRubbishReceiveAmount());
            data.setSewageReceiveAmount(Optional.ofNullable(data.getSewageReceiveAmount()).orElse(0f) + d.getSewageReceiveAmount());
            data.setSewageReceiveTimes(Optional.ofNullable(data.getSewageReceiveTimes()).orElse(0) + d.getSewageReceiveTimes());
            data.setOilyTransportAmount(Optional.ofNullable(data.getOilyTransportAmount()).orElse(0f) + d.getOilyTransportAmount());
            data.setOilyReceiveAmount(Optional.ofNullable(data.getOilyReceiveAmount()).orElse(0f) + d.getOilyReceiveAmount());
            data.setOilyReceiveTimes(Optional.ofNullable(data.getOilyReceiveTimes()).orElse(0) + d.getOilyReceiveTimes());
            data.setElectricityConsumption(Optional.ofNullable(data.getElectricityConsumption()).orElse(0f) + d.getElectricityConsumption());
        });
        list.add(data);
    }

看到这密密麻麻的代码是不是想吐?我都快吐了,身为一个有志之士怎么能写这样的代码呢!太对不起我这句话了“致力于写出思路更加清晰,逻辑性更强,冗余度更低,可维护性和可重用性更高的代码”,所以第二天我就把它优化了

这是改了之后的代码

private void sumDataScreening(List<IpepShipWasteData> list) {
        IpepShipWasteData data = CalculateUtil.getSumValue(list, IpepShipWasteData.class);
        data.setCode("合计");
        list.add(data);
    }

一下就少了好多,用到了CalculateUtil.getSumValue这个方法

想法

从上面的密麻代码中可以发现,我是想把该集合对象的某个属性的值累加起来然后放到该对象的对应属性中。其实就是一直在重复这个操作,遍历这个集合,获取它每个属性的值,然后累加再放到一个新对象的这个属性。是不是突然发现,反射就能做到这个事。所以就有了下面这个工具代码。

工具

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 数值计算工具
 *
 * @author MinWeikai
 * @date 2021/3/13 10:29
 */
public class CalculateUtil {

    /**
     * 计算集合中数值的合计值,并赋予该新对象
     *
     * @param sources 源集合对象
     * @param voClass 源对象
     * @param <T>
     * @return 已计算合计后的源对象
     */
    public static <T> T getSumValue(List<? extends Object> sources, final Class<T> voClass) {
        Field[] fields = voClass.getDeclaredFields();
        T data = null;
        try {
            data = voClass.newInstance();
            T finalData = data;
            sources.stream().forEach(d -> {
                for (Field field : fields) {
                    if (Objects.equals("serialVersionUID", field.getName())) {
                        continue;
                    }
                    Object oldTemp = null;
                    Object newoldTemp = null;
                    try {
                        oldTemp = ReflectionUtil.invokeGetterMethod(d, field.getName());
                        newoldTemp = ReflectionUtil.invokeGetterMethod(finalData, field.getName());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 此处可以自定义匹配类型,或可以结合业务重写该方法,做一些加减乘除的复杂计算
                    switch (field.getType().getSimpleName()) {
                        case "Integer":
                            oldTemp = (int) Optional.ofNullable(oldTemp).orElse(0) +
                                    (int) Optional.ofNullable(newoldTemp).orElse(0);
                            break;
                        case "Float":
                            oldTemp = (float) Optional.ofNullable(oldTemp).orElse(0f) +
                                    (float) Optional.ofNullable(newoldTemp).orElse(0f);
                            oldTemp = new BigDecimal((float) oldTemp)
                                    .setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                            break;
                        case "BigDecimal":
                            oldTemp = new BigDecimal(String.valueOf(Optional.ofNullable(oldTemp).orElse(BigDecimal.ZERO)))
                                    .add(new BigDecimal(String.valueOf(Optional.ofNullable(newoldTemp).orElse(BigDecimal.ZERO))))
                                    .setScale(2, BigDecimal.ROUND_HALF_UP);
                            break;
                        default:
                            oldTemp = null;
                    }
                    if (!Objects.isNull(oldTemp)) {
                        ReflectionUtil.invokeSetterMethod(finalData, field.getName(), oldTemp);
                    }
                }
            });
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return data;
    }


    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        Person data1 = new Person();
        data1.setAge(14);
        data1.setMoney(BigDecimal.ONE);
        data1.setWeight(15.2f);
        list.add(data1);

        Person data2 = new Person();
        data2.setAge(1);
        data2.setMoney(BigDecimal.valueOf(1.4f));
        data2.setWeight(11f);
        list.add(data2);

        Person person = CalculateUtil.getSumValue(list, Person.class);
        System.out.println(person);
    }

}

这个方法有优化的地方或者问题,可以联系我呦!可以在gitee提issue。。

方法中用到了一个反射方法工具

ReflectionUtil工具地址

本文由博客群发一文多发等运营工具平台 OpenWrite 发布

猜你喜欢

转载自blog.csdn.net/weixin_41187876/article/details/114754798