关于map的细节-map.get(Object key)为null

  • 现象
    map.get(Object key)为null,我很确定这个key是我传进去并且自认为是与put进去的值相等。
  • 过程
    我有一个用于储存成绩信息的坐标(key)及成绩值(value)的LinkedHashMap:
private LinkedHashMap<Location, String> gradesMap = new LinkedHashMap<>();

Location类如下(为了篇幅,去掉了getter和setter方法):

public class Location {

        public Location(Integer row, Integer column) {
            this.row = row;
            this.column = column;
        }

        private Integer row;

        private Integer column;
        
        @Override
        public boolean equals(Object obj) {
            Location location = (Location) obj;
            return column.equals(location.getColumn()) && row.equals(location.getRow());
        }
     }

重写了equals是为了使得当Location两个属性分别相等时对象引用就相同。即形如locationA.equals(locationB)这种。我还做了测试:

		Location a = new Location(1,1);
        Location b = new Location(1,1);
        LOGGER.info("相等不:{}", a.equals(b));

输出结果为true。
这里是为了解析如下图所示的excel里面的数据使用:
学生课程成绩信息
按行解析后,将在这里插入图片描述
最后按照预想的做法取出map中的值:
在这里插入图片描述
结果发现这个value始终为null。
很不甘心,又做了个实验:
在这里插入图片描述
输入结果也为null,这时候开始怀疑人生了,按道理说,key都是同一个了,为啥获取到值还是空的。于是就去翻这个map.get(Object key)方法:
在这里插入图片描述
这是LinkedHashMap中的get方法源码,一眼我就瞧见了这个醒目的hash单词,果断去Location类重写了下hashCode方法:
在这里插入图片描述
运行成功!

重温:Java hashCode() 和 equals()的若干问题解答
引用大佬的理解:
对于不会使用到散列表(HashSet, Hashtable, HashMap)来装载对象的情况,才会使用到hashCode,本文刚好是HashMap,本质就是两个对象按照super.hashCode()生成的结果不同,造成equals比较两个对象不相等,故要重写hashCode使用自己的算法让计算后的值相同。

可以将代码分解为多个方法来降低复杂度,例如: 1. 提取一个方法来处理每个实体记录,将其转换为一个 String 类型的 List。 ``` private List<String> processEntity(Entity e, List<String> nameList) { List<String> singleRecord = new ArrayList<>(); nameList.forEach(n -> singleRecord.add(e.get(n) == null ? "" : e.get(n).toString())); if (e.getMetadata().containsKey(ChargeConst.RATE_RULE_DETAIL)) { Set<Map<String, Object>> ruleDtls = (Set<Map<String, Object>>) e.getMetadata().get(ChargeConst.RATE_RULE_DETAIL); Map<Object, Object> mergedMap = mergeRuleDetails(ruleDtls); final List<String> finalSingleRecord = singleRecord; return IntStream.range(0, finalSingleRecord.size()) .mapToObj(i -> finalSingleRecord.get(i).equals("") && mergedMap.get(nameList.get(i)) != null ? mergedMap.get(nameList.get(i)).toString() : finalSingleRecord.get(i)) .collect(Collectors.toList()); } return singleRecord; } ``` 2. 提取一个方法来合并所有规则细节Map。 ``` private Map<Object, Object> mergeRuleDetails(Set<Map<String, Object>> ruleDtls) { return ruleDtls.stream() .flatMap(map -> map.entrySet().stream() .map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue() == null ? "" : entry.getValue()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue)); } ``` 3. 将原来的主方法进行简化,使用上面的两个方法来处理每个实体记录,并将结果添加到 valueList 中。 ``` for (Entity e : rsList) { List<String> singleRecord = processEntity(e, nameList); valueList.add(singleRecord); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值