如何对Map<String, List<Records>>同Key的Records属性累乘并转Map<String, Records>
解决Map中同Key下Records属性累乘的问题
定义的Records类
public class Records { private BigDecimal price; private BigDecimal tos; private BigDecimal share; // 必须补充以下getter/setter方法,否则代码无法正常访问/修改属性 public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public BigDecimal getTos() { return tos; } public void setTos(BigDecimal tos) { this.tos = tos; } public BigDecimal getShare() { return share; } public void setShare(BigDecimal share) { this.share = share; } }
需求说明
现有Map<String, List<Records>>集合,每个Key对应一组Records对象,需对同一Key下所有Records的price、share、tos属性分别执行累乘操作,最终生成每个Key对应单个Records实例的Map<String, Records>。
示例数据
输入
{ "Id1": [ { "price": 3, "share": 4, "tos": 5}, { "price": 2, "share": 3, "tos": 6} ], "Id2": [ { "price": 1, "share": 7, "tos": 4} ] }
期望输出
{ "Id1": { "price": 6, "share": 12, "tos": 30}, "Id2": { "price": 1, "share": 7, "tos": 4} }
原代码的问题分析
你提供的代码存在以下关键问题:
recordData未初始化,直接调用put会抛出NullPointerException- 嵌套循环逻辑混乱:外层已遍历
entrySet,内层又遍历keySet,导致重复处理且关联关系错误 - 未处理列表大小为1的情况:此时
output的属性会为null,不符合期望输出 - 变量作用域不合理:
output在循环中重复创建,但未正确绑定到当前Key
修正后的实现方案
方案1:传统循环实现
private static Map<String, Records> getCumulativeSafFafPaf(Map<String, List<Records>> recordsMap) { // 初始化结果Map,避免空指针 Map<String, Records> recordData = new HashMap<>(); for (Map.Entry<String, List<Records>> entry : recordsMap.entrySet()) { String key = entry.getKey(); List<Records> recordsList = entry.getValue(); Records resultRecord = new Records(); // 初始化累乘初始值为1,兼容列表大小为1的场景 BigDecimal totalPrice = BigDecimal.ONE; BigDecimal totalShare = BigDecimal.ONE; BigDecimal totalTos = BigDecimal.ONE; for (Records record : recordsList) { // 对每个属性执行累乘,并处理精度 totalPrice = DecimalUtil.resetValueWithDefaultScale(totalPrice.multiply(record.getPrice())); totalShare = DecimalUtil.resetValueWithDefaultScale(totalShare.multiply(record.getShare())); totalTos = DecimalUtil.resetValueWithDefaultScale(totalTos.multiply(record.getTos())); } // 设置累乘后的属性值 resultRecord.setPrice(totalPrice); resultRecord.setShare(totalShare); resultRecord.setTos(totalTos); // 将结果存入Map,绑定当前Key recordData.put(key, resultRecord); } return recordData; }
方案2:Java Stream流实现(Java 8+)
如果偏好更简洁的代码,可以用Stream的reduce操作实现累乘:
private static Map<String, Records> getCumulativeSafFafPaf(Map<String, List<Records>> recordsMap) { return recordsMap.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> { Records resultRecord = new Records(); // 对price属性累乘 BigDecimal totalPrice = entry.getValue().stream() .map(Records::getPrice) .reduce(BigDecimal.ONE, (a, b) -> DecimalUtil.resetValueWithDefaultScale(a.multiply(b))); // 对share属性累乘 BigDecimal totalShare = entry.getValue().stream() .map(Records::getShare) .reduce(BigDecimal.ONE, (a, b) -> DecimalUtil.resetValueWithDefaultScale(a.multiply(b))); // 对tos属性累乘 BigDecimal totalTos = entry.getValue().stream() .map(Records::getTos) .reduce(BigDecimal.ONE, (a, b) -> DecimalUtil.resetValueWithDefaultScale(a.multiply(b))); resultRecord.setPrice(totalPrice); resultRecord.setShare(totalShare); resultRecord.setTos(totalTos); return resultRecord; } )); }
关键注意点
- 确保Records类有完整的getter和setter方法,否则无法正常访问和修改属性
DecimalUtil.resetValueWithDefaultScale方法需保证正确处理BigDecimal的精度问题,避免出现无限小数或精度丢失- 累乘初始值设为
BigDecimal.ONE,确保单元素列表的结果与原属性值一致
内容的提问来源于stack exchange,提问作者user19078589
相关产品推荐
相关产品推荐

