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

数组元素更新/新增逻辑异常:循环重复添加问题求助

问题描述

我需要对比两个数据源(一个Report列表和一个ChargeType的Map),实现以下逻辑:

  • 如果ChargeType的名称在Report列表中已存在,就累加对应的金额和数量到该Report的bscsAmount和bscsQuantity
  • 如果不存在,就创建新的Report对象添加到列表中

但当前代码在循环时,即便匹配到了已存在的元素,仍会重复执行添加操作,导致列表出现大量重复项。我认为应该在遍历完Report列表确认没有匹配项后,再执行添加操作,想知道可行的实现方式。

原错误代码

for(var bscsEntry : bscsChargeTypemap.entrySet()) {
    Report report = new Report();
    for(int i = 0; i < reportDataList.size(); i++) {
        if(bscsEntry.getValue().getChargeTypeName().equalsIgnoreCase(reportDataList.get(i).getChargeTypeName())) {
            reportDataList.get(i).setBscsAmount(bscsEntry.getValue().getAmount());
            reportDataList.get(i).setBscsQuantity(bscsEntry.getValue().getQuantity());
        }else {
            report.setChargeTypeName(bscsEntry.getValue().getChargeTypeName());
            report.setBscsAmount(bscsEntry.getValue().getAmount());
            report.setBscsAmount(bscsEntry.getValue().getQuantity()); // 笔误:应为setBscsQuantity
            reportDataList.add(report);
        }
    }
}

数据示例

现有Report列表

Type : [Name : TypeA, Amount : 10.0 , Quantity : 1]
Type : [Name : TypeB, Amount : 5.0 , Quantity : 2]
Type : [Name : TypeC, Amount : 55.0 , Quantity : 1]
Type : [Name : TypeD, Amount : 10.0 , Quantity : 2]

Map中的ChargeType集合

Type : [Name : TypeA, Amount : 10.0 , Quantity : 1]
Type : [Name : TypeB, Amount : 5.0 , Quantity : 2]
Type : [Name : TypeE, Amount : 65.0 , Quantity : 1]
Type : [Name : TypeF, Amount : 100.0 , Quantity : 2]

预期结果

Type : [Name : TypeA, Amount : 20.0 , Quantity : 2]
Type : [Name : TypeB, Amount : 10.0 , Quantity : 4]
Type : [Name : TypeC, Amount : 55.0 , Quantity : 1]
Type : [Name : TypeD, Amount : 10.0 , Quantity : 2]
Type : [Name : TypeE, Amount : 65.0 , Quantity : 1]
Type : [Name : TypeF, Amount : 100.0 , Quantity : 2]

相关POJO类

ChargeType类

public class ChargeType {

    private String chargeTypeName;
    private Double amount;
    private Integer quantity;
    
    public ChargeType() {
        chargeTypeName = "";
        amount = Double.parseDouble("0");
        quantity = 0;
    }
    
    public ChargeType(String chargeTypeName, Double amount, Integer quantity) {
        this.chargeTypeName = chargeTypeName;
        this.amount = amount;
        this.quantity = quantity;
    }

    public String getChargeTypeName() {
        return chargeTypeName;
    }

    public void setChargeTypeName(String chargeTypeName) {
        this.chargeTypeName = chargeTypeName;
    }

    public Double getAmount() {
        return amount;
    }

    public void setAmount(Double amount) {
        this.amount = amount;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }
}

Report类

public class Report {
    private String chargeTypeName;
    private Double brmAmount;
    private Integer brmQuantity;
    private Double bscsAmount;
    private Integer bscsQuantity;
    private String remarks;
    
    public Report() {
        chargeTypeName = "";
        brmAmount = Double.parseDouble("0");
        brmQuantity = 0;
        bscsAmount = Double.parseDouble("0");
        bscsQuantity = 0;
        remarks = "";
    }

    public String getChargeTypeName() {
        return chargeTypeName;
    }

    public void setChargeTypeName(String chargeTypeName) {
        this.chargeTypeName = chargeTypeName;
    }

    public Double getBrmAmount() {
        return brmAmount;
    }

    public void setBrmAmount(Double brmAmount) {
        this.brmAmount = brmAmount;
    }

    public Integer getBrmQuantity() {
        return brmQuantity;
    }

    public void setBrmQuantity(Integer brmQuantity) {
        this.brmQuantity = brmQuantity;
    }

    public Double getBscsAmount() {
        return bscsAmount;
    }

    public void setBscsAmount(Double bscsAmount) {
        this.bscsAmount = bscsAmount;
    }

    public Integer getBscsQuantity() {
        return bscsQuantity;
    }

    public void setBscsQuantity(Integer bscsQuantity) {
        this.bscsQuantity = bscsQuantity;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}

解决方案

方案1:使用标志位判断匹配状态

核心思路:对每个ChargeType,先遍历Report列表查找同名项,找到则累加数据;遍历完整个列表都没找到,再创建新Report添加。

修改后的代码:

for(var bscsEntry : bscsChargeTypemap.entrySet()) {
    ChargeType chargeType = bscsEntry.getValue();
    boolean isMatched = false;
    // 遍历Report列表查找匹配项
    for(Report report : reportDataList) {
        if(chargeType.getChargeTypeName().equalsIgnoreCase(report.getChargeTypeName())) {
            // 累加金额和数量(而非直接覆盖)
            report.setBscsAmount(report.getBscsAmount() + chargeType.getAmount());
            report.setBscsQuantity(report.getBscsQuantity() + chargeType.getQuantity());
            isMatched = true;
            break; // 找到匹配项后直接跳出循环,避免无效遍历
        }
    }
    // 未找到匹配项,添加新Report
    if(!isMatched) {
        Report newReport = new Report();
        newReport.setChargeTypeName(chargeType.getChargeTypeName());
        newReport.setBscsAmount(chargeType.getAmount());
        newReport.setBscsQuantity(chargeType.getQuantity());
        reportDataList.add(newReport);
    }
}

方案2:用Map优化查找效率(推荐)

如果reportDataList数据量较大,遍历查找效率低,可先将列表转为以chargeTypeName为Key的Map,将查找复杂度从O(n)降到O(1):

// 先把Report列表转成Map,统一转小写作为Key避免大小写问题
Map<String, Report> reportMap = new HashMap<>();
for(Report report : reportDataList) {
    reportMap.put(report.getChargeTypeName().toLowerCase(), report);
}

// 遍历ChargeType的Map处理数据
for(var bscsEntry : bscsChargeTypemap.entrySet()) {
    ChargeType chargeType = bscsEntry.getValue();
    String key = chargeType.getChargeTypeName().toLowerCase();
    Report report = reportMap.get(key);
    
    if(report != null) {
        // 找到匹配项,累加数据
        report.setBscsAmount(report.getBscsAmount() + chargeType.getAmount());
        report.setBscsQuantity(report.getBscsQuantity() + chargeType.getQuantity());
    } else {
        // 未找到,创建新Report并添加到列表和Map
        Report newReport = new Report();
        newReport.setChargeTypeName(chargeType.getChargeTypeName());
        newReport.setBscsAmount(chargeType.getAmount());
        newReport.setBscsQuantity(chargeType.getQuantity());
        reportDataList.add(newReport);
        reportMap.put(key, newReport);
    }
}

原代码问题总结

  1. 重复添加:内部循环的else分支直接添加元素,导致同一个ChargeType被多次添加
  2. 逻辑错误:原代码直接覆盖bscsAmount和bscsQuantity,不符合预期的累加需求
  3. 代码笔误:report.setBscsAmount(bscsEntry.getValue().getQuantity());应为setBscsQuantity,导致数量未正确设置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:25:25