Java将List分组为多层Map统计时出现NullPointerException问题
问题原因
空指针及代码不生效是多个错误共同导致的,核心问题如下:
- 变量名拼写混乱:代码中
mapModelCode和mapaModelCode、mapModelYear和mapaModelYear混用,拼写错误的变量实际取值为null - 取值逻辑完全错误:else分支中
mapModelCode = mapKey.get(modelCode)写法错误,mapKey的键是Emp类的key字段,不是modelCode,用modelCode从mapKey取值只会返回null,后续调用mapModelCode.get()直接触发空指针 - 判断逻辑存在缺陷:只要
key不存在或者key下的modelCode不存在,就直接新建空的mapModelCode覆盖mapKey中对应key的值,会导致同一个key下已存在的其他modelCode数据被清空 - 层级访问逻辑错误:
mapModelCode的键是modelCode,调用mapModelCode.get(modelYear)完全不符合嵌套层级的设计,取不到正确值
修复方案
推荐直接用Java 8+的computeIfAbsent简化嵌套Map的初始化逻辑,避免手写判断出错,修复后的代码如下:
public static Map<String,Map<String, Map<String, Integer>>> getTotal(Map<AnyEnum, List<Emp>> empMap){ Map<String,Map<String, Map<String, Integer>>> mapKey = new HashMap<>(); for (List<Emp> empList : empMap.values()) { for(Emp emp: empList) { String key = emp.getKey(); String modelCode = emp.getModelCode(); String modelYear = emp.getModelYear(); // 逐层初始化嵌套Map,不存在就新建,存在就直接返回已有对象 mapKey.computeIfAbsent(key, k -> new HashMap<>()) .computeIfAbsent(modelCode, k -> new HashMap<>()) .merge(modelYear, 1, Integer::sum); // 计数累加,不存在就设为1,存在就加1 } } return mapKey; }
如果需要兼容低版本Java无法使用computeIfAbsent,可以把判断逻辑修正如下:
public static Map<String,Map<String, Map<String, Integer>>> getTotal(Map<AnyEnum, List<Emp>> empMap){ Map<String,Map<String, Map<String, Integer>>> mapKey = new HashMap<String,Map<String, Map<String, Integer>>>(); for (Map.Entry<AnyEnum, List<Emp>> entry : empMap.entrySet()) { List<Emp> empList = entry.getValue(); for(Emp emp: empList) { String key = emp.getKey(); String modelCode = emp.getModelCode(); String modelYear = emp.getModelYear(); // 先处理key层级 Map<String, Map<String, Integer>> mapModelCode = mapKey.get(key); if(mapModelCode == null) { mapModelCode = new HashMap<>(); mapKey.put(key, mapModelCode); } // 再处理modelCode层级 Map<String, Integer> mapModelYear = mapModelCode.get(modelCode); if(mapModelYear == null) { mapModelYear = new HashMap<>(); mapModelCode.put(modelCode, mapModelYear); } // 最后处理计数 Integer count = mapModelYear.get(modelYear); mapModelYear.put(modelYear, count == null ? 1 : count + 1); } } return mapKey; }
运行上述代码后得到的结果结构和预期完全一致。
内容的提问来源于stack exchange,提问作者oitathi
相关产品推荐
相关产品推荐

