优化java加权方法

1. 场景

需要对不同类型对象、不同类型的字段,求加权值;

2. 抽象字段

使用 Function 抽象字段,后面处理 字段类型;

java 复制代码
	private BigDecimal getWeightValueByListAndFunc(List<ZjCentralEnterprise> filterList, Function<ZjCentralEnterprise, BigDecimal> heatValueGet
            , Function<ZjCentralEnterprise, BigDecimal> qtyGetFunc, int scale) {
        Map<String, BigDecimal> heatValueMap = new HashMap<>();
        Map<String, BigDecimal> quantityMap = new HashMap<>();
        List<String> keys = new ArrayList<>();
        for (int i = 0; i < filterList.size(); i++) {
            String key = String.valueOf(i);
            keys.add(key);
            heatValueMap.put(key, heatValueGet.apply(filterList.get(i)));
            quantityMap.put(key, qtyGetFunc.apply(filterList.get(i)));
        }
        BigDecimal weight = NumberUtils.calculateAverageWeight2(heatValueMap, quantityMap, scale);
        return weight;
    }

2. 抽象对象

使用 T 抽象对象

java 复制代码
    public static <T> BigDecimal weightedAverage(List<T> list,
                                                 Function<T, BigDecimal> valueFunc,
                                                 Function<T, BigDecimal> weightFunc,
                                                 int scale) {
        if (list == null || list.isEmpty()) {
            return BigDecimal.ZERO;
        }

        Map<String, BigDecimal> valueMap = new HashMap<>();
        Map<String, BigDecimal> weightMap = new HashMap<>();

        for (int i = 0; i < list.size(); i++) {
            String key = String.valueOf(i);
            T item = list.get(i);
            valueMap.put(key, valueFunc.apply(item));
            weightMap.put(key, weightFunc.apply(item));
        }

        return NumberUtils.calculateAverageWeight2(valueMap, weightMap, scale);
    }

    public static <T> Integer weightedAverage2(List<T> list,
                                               Function<T, Integer> valueFunc,
                                               Function<T, BigDecimal> weightFunc) {
        if (list == null || list.isEmpty()) {
            return 0;
        }

        Map<String, BigDecimal> valueMap = new HashMap<>();
        Map<String, BigDecimal> weightMap = new HashMap<>();

        for (int i = 0; i < list.size(); i++) {
            String key = String.valueOf(i);
            T item = list.get(i);
            valueMap.put(key, new BigDecimal(String.valueOf(valueFunc.apply(item))));
            weightMap.put(key, weightFunc.apply(item));
        }

        BigDecimal bg = NumberUtils.calculateAverageWeight2(valueMap, weightMap, 0);
        return bg.intValue();
    }

3. 抽象字段类型

使用 v 抽象字段类型

bash 复制代码
public static <T, V extends Number> BigDecimal calcWeightedAverage(
            List<T> list,
            Function<T, V> valueFunc,
            Function<T, BigDecimal> weightFunc,
            int scale
    ) {
        if (list == null || list.isEmpty()) {
            return BigDecimal.ZERO;
        }

        Map<String, BigDecimal> valueMap = new HashMap<>();
        Map<String, BigDecimal> weightMap = new HashMap<>();

        for (int i = 0; i < list.size(); i++) {
            String key = String.valueOf(i);
            T item = list.get(i);

            // 核心:自动将任意 Number 转为 BigDecimal(兼容 Integer/Long/Double)
            V value = valueFunc.apply(item);
            BigDecimal valueBig = new BigDecimal(value.toString());

            BigDecimal weight = weightFunc.apply(item);

            valueMap.put(key, valueBig);
            weightMap.put(key, weight);
        }

        // 调用你原有加权计算方法
        return NumberUtils.calculateAverageWeight2(valueMap, weightMap, scale);
    }

4. 公共方法

java 复制代码
public static BigDecimal calculateAverageWeight2(
            Map<String, BigDecimal> cumPurchaseHeatValueMap,
            Map<String, BigDecimal> cumPurchaseMap, int scale) {

        if (cumPurchaseHeatValueMap == null || cumPurchaseMap == null) {
            return null;
        }
        List<String> keyList = new ArrayList<>(cumPurchaseHeatValueMap.keySet());
        BigDecimal sumProduct = BigDecimal.ZERO;  // 分子:热值与采购数量的乘积之和
        BigDecimal sumQuantity = BigDecimal.ZERO; // 分母:采购数量之和

        for (String key : keyList) {
            BigDecimal heatValue = cumPurchaseHeatValueMap.get(key);
            BigDecimal purchaseQuantity = cumPurchaseMap.get(key);

            // 如果任一值为null,跳过该物料
            if (heatValue != null && purchaseQuantity != null && heatValue.doubleValue() > 0 && purchaseQuantity.doubleValue() > 0) {
                sumProduct = sumProduct.add(heatValue.multiply(purchaseQuantity));
                sumQuantity = sumQuantity.add(purchaseQuantity);
            }
        }

        // 如果分母为0,返回null
        if (sumQuantity.compareTo(BigDecimal.ZERO) == 0) {
            return null;
        }

        return sumProduct.divide(sumQuantity, scale, RoundingMode.HALF_UP);
    }

5. 使用

第二个参数类型 和返回值类型 相同

java 复制代码
        Integer heatValue2 = NumberUtils.calcWeightedAverage(list, ZjPowerPlantCoalData::getCalorificValue, ZjPowerPlantCoalData::getQuantity, 0).intValue();
        Long heatValue3 = NumberUtils.calcWeightedAverage(list, ZjPowerPlantCoalData::getCalorificValue, ZjPowerPlantCoalData::getQuantity, 0).longValue();
        Double closingPrice = NumberUtils.calcWeightedAverage(list, ZjPowerPlantCoalData::getClosingPrice, ZjPowerPlantCoalData::getQuantity, 2).doubleValue();
        BigDecimal closingPrice2 = NumberUtils.calcWeightedAverage(list, ZjPowerPlantCoalData::getClosingPrice, ZjPowerPlantCoalData::getQuantity, 2);
相关推荐
xcl09254 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐5 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长6 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn6 小时前
Spring 注解使用详解
java·spring
一条小小yu6 小时前
Spring IoC的理解
java·后端·spring
落魄实习生6 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈7 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白8 小时前
核心功能(Service接口)
java·mybatis
乌暮9 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习