Java中如何按退款条件遍历List集合完成价格加减合计以生成贷方收据
现存代码问题梳理
- 方法内定义的
executed属于局部变量,每次调用receipt()方法时都会被重置为false,无法实现「计算逻辑只执行一次」的目标 - 循环判断条件
tra.isHasCondition1 == true && !executed会让代码只命中第一笔带退款标记的交易,直接跳过剩余交易的遍历累加,不符合全量计算的要求 - 计算逻辑和需求完全脱节:冗余了
getPurseCredit()、分支内重复累加价格的无关逻辑,没有按退款标记实现统一的加减规则 - 布尔值判断写法冗余:
tra.isHasCondition1 == true可简化为tra.isHasCondition1 - 绝对值计算冗余:
Math.abs(-total)和Math.abs(total)效果完全一致
改造实现
- 将「是否已完成收据计算」的标记从方法内局部变量改为成员变量,才能跨方法调用保存执行状态,避免前端重复点击触发二次计算
- 去掉循环内的单次命中限制,遍历所有交易时按规则独立完成加减计算
- 统一在获取交易价格时就用
Math.abs()处理数据库存储的负号,避免负数干扰计算结果 - 移除和需求无关的冗余计算逻辑
改造后可运行代码
// 成员变量:标记收据是否已完成计算,防止重复执行 private boolean receiptCalculated = false; private List<Transaction> lsta; // 金额类计算建议用BigDecimal规避浮点精度问题,若原代码用double可对应替换 private BigDecimal total = BigDecimal.ZERO; public void receipt() { // 已完成计算直接退出,不重复处理 if (receiptCalculated) { return; } try { List<Transaction> lst = gvar.get(prd); // 先清空已处理交易列表,避免重复添加 lsta.clear(); System.out.println("Total before calculation: " + total); for (Transaction tra : lst) { // 取交易价格绝对值,兼容数据库存储的负价格 BigDecimal actualPrice = BigDecimal.valueOf(Math.abs(tra.getPrice())); // 按退款标记执行加减逻辑 if (tra.isHasCondition1()) { // 条件1为true(已退款):从总金额中扣除 total = total.subtract(actualPrice); } else { // 条件1为false(未退款):累加进总金额 total = total.add(actualPrice); } // 将处理完成的交易加入收据列表 lsta.add(tra); } // 若总金额为负,取绝对值消除负号,符合Math.abs的使用需求 if (total.compareTo(BigDecimal.ZERO) < 0) { total = total.abs(); System.out.println("Total after Math.abs: " + total); } // 标记计算完成,后续触发直接跳过 receiptCalculated = true; System.out.println("Final total amount: " + total); } catch (Exception ex) { ex.printStackTrace(); } }
关键逻辑说明
- 执行标记的存储位置:成员变量
receiptCalculated会随当前对象实例存活,下次前端点击触发receipt()时会直接跳过计算,完全匹配「逻辑仅执行一次」的要求 - 全量遍历逻辑:循环内不再加执行状态的拦截条件,列表内每一笔交易都会按退款标记完成对应加减,不会漏掉任何产品的价格计算
- 负价格处理:在获取每笔交易金额时就取绝对值,从源头避免数据库存储的负价格干扰计算;如果最终总金额出现负数,再统一取绝对值,和原本用
Math.abs去负号的设计一致 - 收据列表维护:遍历前清空
lsta,避免每次方法调用时重复添加已处理过的交易
注:如果项目中原本用
double存储金额,可将代码中的BigDecimal替换为double,保留Math.abs()的处理逻辑即可,注意规避浮点计算的精度偏差。
内容的提问来源于stack exchange,提问作者WScoder
相关产品推荐
相关产品推荐

