数组元素更新/新增逻辑异常:循环重复添加问题求助
问题描述
我需要对比两个数据源(一个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); } }
原代码问题总结
- 重复添加:内部循环的
else分支直接添加元素,导致同一个ChargeType被多次添加 - 逻辑错误:原代码直接覆盖
bscsAmount和bscsQuantity,不符合预期的累加需求 - 代码笔误:
report.setBscsAmount(bscsEntry.getValue().getQuantity());应为setBscsQuantity,导致数量未正确设置
内容的提问来源于stack exchange,提问作者poojay
相关产品推荐
相关产品推荐

