• 当Map的值为NULL


    最近在开发过程中遇到了一个非常令人费解的情况,排查了将近一早上还没找到头绪,还是在师兄的帮助下,才发现了问题。

    问题复现

    先看一段代码:

    // 调用远程RPC方法,获取map
    Map<String, Object> map = remoteMethod.queryMap();
    // 如果包含对应key,则进行业务处理
    if(map.contains(KEY)) {
        String value = (String)map.get(KEY);
        System.out.println(value);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这段代码乍一看,逻辑没有什么问题,如果查询到的map包含这个key,就拿到这个key的值,并转为String类型,并打印这个value。
    但是事实上,程序会偶发的打印出 null ,所以我就开始排查是否是因为map.get(KEY) = null,排查方式如下:

    // 调用远程RPC方法,获取map
    Map<String, Object> map = remoteMethod.queryMap();
    // 如果包含对应key,则进行业务处理
    System.out.println(JSON.toJsonString(map));
    
    • 1
    • 2
    • 3
    • 4

    结果对应的输出也只是一个非常简单的{}字符串,这个时候我就非常懵逼了,明明map中没有对应的key,为啥还会执行map.contains(KEY)的逻辑呢?

    问题原因

    最后,经过排查,发现了两个问题

    1. HashMap的value可以为null,这就意味着虽然hashMap.get(KEY) == null,但是hashMap.contains(KEY) == true也是完全可以存在的。这就是第一段代码出现问题的原因
    2. Fastjson和Gson默认不会打印value为null的键值对,即当hashMap.get(KEY) == null && hash.contains(KEY)时,常见的json框架如没有特殊制定的情况下,是不会将{KEY:null}打印出来的,这也是第二段代码没有排查出来问题的原因

    结合这两个问题来看,原因就十分明显了,远程的RPC服务返回的Map中的value包含null值,导致仍然可以进入正常的业务逻辑中;同时,又因为没有json默认不会打印value=null的键值对,所以导致了问题排查的困难

    解决方案

    在开发过程中,尤其是调用外部接口或者从数据库获取数据的时候,由于Java是强类型,我们都喜欢把扩展字段的类型封装成Map,然后再根据具体的场景将value强转为不同的类型(如String),这个时候,无论是#get还是#put都需要相当注意:

    1. #put方法在使用的时候,如果value=null,就尽量不要put进去
    2. 在要对value处理的情况下,尽量不要使用#contains判断key的存在,要使用(V = (map.get(KEY))) != null会更好一点

    感悟总结

    Map实现类的区别,是面试很常见的一个问题,其中的一个不同点就是key=null和value=null的情况,但是在看书的时候只是匆匆略过,知道有这么一个事情,有点不以为意,只有真正踩坑的时候,才明白有多重要~

    HashMap: key和value均可以为null
    HashTable:key和value均不可以为null
    ConcurrentHashMap:key和value均不可以为null

    其实,仔细想了一下,常见的json框架默认不打印{KEY:null}也是有原因的,因为如果很多json2Str方法的作用都是打印日志或者持久化到数据库中的,如果把大量的value=null打印出来,尤其是在数据库持久化的时候,会产生大量无用的数据,多少有点浪费的。不过跟资金相关的日志,建议还是把null值打印出来比较好,更方便排查问题了:)

  • 相关阅读:
    Pytorch中张量的维度扩张与广播操作示例
    Vite依赖预构建
    【黑猩猩算法】基于加权反对技术和贪婪搜索进化黑猩猩优化算法求解多模态工程问题附matlab代码
    盘点49个Python网站项目Python爱好者不容错过
    行业分析网站-网站分析软件-免费网站详细数据分析软件
    T2T-ViT:更多的局部结构信息,更高效的主干网络 | ICCV 2021
    MySQL安装教程(Windows版)
    Java-校验规则Integer使用 @NotEmpty注解报错
    sqlserver查询多个分类的最新时间数据
    7. Reverse Integer
  • 原文地址:https://blog.csdn.net/coder_what/article/details/126092564