You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java 8 Stream简化成本计算代码并保留原对象引用?

使用Java 8 Stream简化成本计算代码的方案

你的思路方向是对的,但原写法的问题在于把单个StartingMaterialMatrix对象作为Stream元素,没法同时处理两个blending项的逻辑。我们可以换个思路:把**每个需要计算的blending项(矩阵+浓度)**作为Stream的元素,这样就能统一复用计算逻辑,避免重复的if判断。

简化后的代码(Java 8兼容,类型安全版本)

首先,我们可以定义一个私有的内部类来封装blending项的矩阵和浓度,避免数组的强制转换:

private static class BlendingItem {
    private final StartingMaterial matrix;
    private final Double concentration;

    BlendingItem(StartingMaterial matrix, Double concentration) {
        this.matrix = matrix;
        this.concentration = concentration;
    }

    public StartingMaterial getMatrix() { return matrix; }
    public Double getConcentration() { return concentration; }
}

private double calculateBCMMatrixCostForAnalyte(Long startingMaterialId) {
    StartingMaterialMatrix smm = startingMaterialMatrixRepository.findByStartingMaterialId(startingMaterialId);
    
    return Precision.round(
        Stream.of(
            new BlendingItem(smm.getBlending1Matrix(), smm.getBlending1MatrixConcentration()),
            new BlendingItem(smm.getBlending2Matrix(), smm.getBlending2MatrixConcentration())
        )
        .filter(item -> item.getConcentration() != null) // 过滤浓度为空的项
        .mapToDouble(item -> {
            // 复用原代码的成本计算逻辑
            double materialCost = priceService.findNeatMaterialCostByStartingMaterialId(item.getMatrix().getId());
            return materialCost * item.getConcentration() / 1_000_000.0;
        })
        .sum(), // 自动累加所有有效项的成本
        4
    );
}

代码说明

  1. 封装blending项:用BlendingItem类把每个blending的矩阵和浓度绑定在一起,保证类型安全,避免数组的强制转换。
  2. Stream化处理:把两个blending项转换成Stream元素,这样可以统一执行过滤、计算逻辑,替代原代码中重复的if判断和累加操作。
  3. 过滤无效项:通过filter去掉浓度为null的项,对应原代码中的if (concentration != null)判断。
  4. 统一计算逻辑:用mapToDouble对每个有效项计算成本,最后调用sum()自动累加,替代原代码中的手动+=操作。
  5. 保持精度控制:最后依然用Precision.round保留4位小数,和原代码逻辑完全一致。

更简洁的版本(如果不介意数组的强制转换)

如果不想定义额外的类,也可以直接用Object[]来封装,虽然少了类型安全,但代码更短:

private double calculateBCMMatrixCostForAnalyte(Long startingMaterialId) {
    StartingMaterialMatrix smm = startingMaterialMatrixRepository.findByStartingMaterialId(startingMaterialId);
    
    return Precision.round(
        Stream.of(
            new Object[]{smm.getBlending1Matrix(), smm.getBlending1MatrixConcentration()},
            new Object[]{smm.getBlending2Matrix(), smm.getBlending2MatrixConcentration()}
        )
        .filter(item -> item[1] != null)
        .mapToDouble(item -> {
            StartingMaterial matrix = (StartingMaterial) item[0];
            Double concentration = (Double) item[1];
            return priceService.findNeatMaterialCostByStartingMaterialId(matrix.getId()) * concentration / 1_000_000.0;
        })
        .sum(),
        4
    );
}

对你原写法的问题分析

你之前的写法把smm作为Stream的唯一元素,这样只能处理一次blending1的逻辑,没法同时处理blending2。而我们把每个blending项作为Stream元素后,就能一次性处理所有需要计算的项,既简化了重复代码,也符合Stream的设计初衷。

内容的提问来源于stack exchange,提问作者Jay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:07:46