优化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);
相关推荐
人活一口气7 小时前
Spring Boot与AIGC的完美结合:从零搭建智能内容生成平台
java·spring boot·aigc
像我这样帅的人丶你还9 小时前
Java 后端详解(三):全局异常处理与 JPA 数据库映射
java·后端
NE_STOP9 小时前
vibe Coding -- 小项目实战
java
未秃头的程序猿15 小时前
Java 26正式发布!这3个新特性,让代码量直接减半
java·后端·面试
用户2986985301415 小时前
Word 文档文本查找与替换的 Java 实现方案
java·后端
阿哉15 小时前
Nacos 服务发现源码:藏在背后的两套事件机制,90%的人只讲了一半
java
咖啡八杯16 小时前
GoF设计模式——命令模式
java·设计模式·架构
AI人工智能_电脑小能手16 小时前
【大白话说Java面试题 第125题】【并发篇】第25题:说说 Java 线程的中断机制
java·后端·面试
Java内核笔记16 小时前
Spring Security 源码解析(六)无状态 JWT 实践:Session 共享与自定义过滤器
java·后端
荣码16 小时前
LangGraph多Agent协作:3个Agent干活比1个强,但我踩了4个坑
java·python