优化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);
相关推荐
CODE202203182 分钟前
promptfoo自定义prompt生成器
java·前端·prompt
_waylau6 分钟前
“Java+AI全栈工程师”问答02:Spring Boot 自动配置原理
java·开发语言·spring boot·后端·spring
JAVA面经实录9176 分钟前
Java架构师最终完整版学习路线图
java·开发语言·学习
上海蓝色星球7 分钟前
从工具到资产:CER V2.0 造价机器人如何重构企业核心竞争力
java·数据库·mysql
spencer_tseng8 分钟前
System2.java
java·system
222you11 分钟前
Claude Code接入DeepSeek-v4模型
java·服务器·前端
i220818 Faiz Ul13 分钟前
高校教务|教务管理|基于springboot+vue的高校教务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·高校教务系统
Ting-yu15 分钟前
SpringCloud快速入门(4)---- nacos安装与使用
java·spring·spring cloud
木子墨51615 分钟前
工程算法实战 | 从LRU到手写本地缓存:LinkedHashMap → 双向链表+哈希表 → Caffeine 原理
java·数据结构·算法·链表·缓存
无尽冬.21 分钟前
个人八股之三层架构
java·经验分享·后端·架构·异世界