当前位置: 首页 > news >正文

建设行政主管部门政务网站本地网站建设方案信息大全

建设行政主管部门政务网站,本地网站建设方案信息大全,网站制作 文案,如何让百度收录我的网站一、背景 最近设计某个类库时使用了 ConcurrentHashMap 最后遇到了 value 为 null 时报了空指针异常的坑。 本文想探讨下以下几个问题#xff1a; #xff08;1#xff09; Map接口的常见子类的 kv 对 null 的支持情况。 #xff08;2#xff09;为什么 ConcurrentHashM…一、背景 最近设计某个类库时使用了 ConcurrentHashMap 最后遇到了 value 为 null 时报了空指针异常的坑。 本文想探讨下以下几个问题 1 Map接口的常见子类的 kv 对 null 的支持情况。 2为什么 ConcurrentHashMap 不支持 key 和 value 为 null? 3如果 value 可能为 null 该如何处理 4有哪些线程安全的 Java Map 类 5) 常见的 Map 接口的子类如 HashMap、TreeMap 、ConcurrentHashMap 、ConcurrentSkipListMap 的使用场景。 二、探究 2.1 Map接口的常见子类的 kv 对 null 的支持情况 下图来源于孤尽老师 《码出高效》 第 6 章 数据结构与集合 2.2 为什么 ConcurrentHashMap 不支持 key 和 value 为 null? 从 java.util.concurrent.ConcurrentHashMap#put 方法的注释和源码中可以非常容易得看出不支持 key 和 value null。 /*** Maps the specified key to the specified value in this table.* Neither the key nor the value can be null.** pThe value can be retrieved by calling the {code get} method* with a key that is equal to the original key.** param key key with which the specified value is to be associated* param value value to be associated with the specified key* return the previous value associated with {code key}, or* {code null} if there was no mapping for {code key}* throws NullPointerException if the specified key or value is null*/public V put(K key, V value) {return putVal(key, value, false);}/** Implementation for put and putIfAbsent */final V putVal(K key, V value, boolean onlyIfAbsent) {if (key null || value null) throw new NullPointerException();int hash spread(key.hashCode());// 省略其他}那么为什么不支持 key 和 value 为 null 呢 据查阅资料ConcurrentHashMap 的作者 Doug Lea 自己的描述 The main reason that nulls aren’t allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) is that ambiguities that may be just barely tolerable in non-concurrent maps can’t be accommodated. The main one is that if map.get(key) returns null, you can’t detect whether the key explicitly maps to null vs the key isn’t mapped. In a non-concurrent map, you can check this via map.contains(key), but in a concurrent one, the map might have changed between calls. 可知 ConcurrentHashMap 是线程安全的容器如果 ConcurrentHashMap 允许存放 null 值那么当一个线程调用 get(key) 方法时返回 null 可能有两种情况 (1) 一种是这个 key 不存在于 map 中 (2) 另一种是这个 key 存在于 map 中但是它的值为 null。 这样就会导致线程无法判断这个 null 是什么意思。 在非并发的场景下可以通过 map.contains(key)检查是否包括该 key从而断定是不存在 key 还是存在key 但值为 null但是在并发场景下判断后调用其他 api 之间 map 的数据已经发生了变化无法保证对同一个 key 操作的一致性。 2.3 怎么解决 2.3.1 封装 put 方法使用前判断 建议封装 put 方法统一使用该方法对 ConcurrentHashMap 的 put 操作进行封装当 value 为 null 时直接 return 即可。 MapString, Person map new ConcurrentHashMap();// 封装 put 操作为 null 时返回 private void putPerson(String key, Person value){if(value null){return;}map.put(key, value); }2.3.2 使用 Optional 类型 使用 Optional // 创建一个 ConcurrentHashMapString, OptionalString MapString, OptionalString map new ConcurrentHashMap();// 插入或更新 key-value 对 map.computeIfAbsent(name, k - Optional.ofNullable(Alice)); // 如果 name 不存在则插入 (name, Optional.of(Alice)) map.computeIfAbsent(age, k - Optional.ofNullable(null)); // 如果 age 不存在则插入 (age, Optional.empty())// 获取 value OptionalString name map.get(name); // 返回 Optional.of(Alice) OptionalString age map.get(age); // 返回 Optional.empty() OptionalString gender map.get(gender); // 返回 null2.3.3 自定义一个表示 null 的类 自定义表示 null 的类 然后对 put 和 get 操作进行二次封装参考代码如下 // 定义一个表示 null 的类 public class NullValue extends Person{}// 创建一个 ConcurrentHashMapString, Object private MapString, Person map new ConcurrentHashMap();private static final NullValue nullValue new NullValue();//使用示例 值不为 null 时 putPerson(1002, new Person(张三));//使用示例 值为 null 时 putPerson(1003, null);// 封装设置操作 private void putPerson(String key,Person person){if(person null){map.put(key, nullValue);return;}map.put(key, person); }// 封装获取操作 private Person getPerson(String key){if(key null){return;}Person person map.get(key);if(person instanceof NullValue){return null;}return person; } 2.3.4 使用其他线程安全的 Java Map 类 Java 中也有支持 key 和 value 为 null 的线程安全的集合类比如 ConcurrentSkipListMap (JDK) 和 CopyOnWriteMap (三方)。 ConcurrentSkipListMap 是一个基于跳表的线程安全的 map它使用锁分段的技术来提高并发性能。它允许 key 和 value 为 null但是它要求 key 必须实现 Comparable 接口或者提供一个 Comparator。CopyOnWriteMap 是一个基于数组的线程安全的 map它使用写时复制的策略来保证并发访问的正确性。它允许 key 和 value 为 null。 注意 JDK 中没有提供 CopyOnWriteMap很多三方类库提供了对应的工具类。如org.apache.kafka.common.utils.CopyOnWriteMap。 2.4 常见的 Map 接口的子类的使用场景 Map 接口有很多子类那么他们各自的适用场景是怎样的呢 使用场景主要取决于以下几个方面 是否需要线程安全如果需要在多线程环境下操作 Map那么应该使用 ConcurrentHashMap、ConcurrentSkipListMap它们都是并发安全的。而 HashMap、TreeMap、HashTable和LinkedHashMap则不是并且 HashTable已经被 ConcurrentHashMap取代。是否需要保证键的顺序如果需要按照键的自然顺序或者插入顺序遍历 Map那么应该使用 TreeMap或者 LinkedHashMap它们都是有序的。而 ConcurrentSkipListMap也是有序的并且支持范围查询。其他类则是无序的。是否需要高效地访问和修改如果需要快速地获取和更新 Map中的元素那么应该使用 HashMap或者 ConcurrentHashMap它们都是基于散列函数实现的具有较高的性能。 而 TreeMap和 ConcurrentSkipListMap则是基于平衡树实现的具有较低的性能。CopyOnWriteMap 则是基于数组实现的并发写操作会复制整个数组因此写操作开销很大。 在选择合适的 Map 接口实现时需要根据具体需求和场景进行权衡。 三、总结 基本功很重要有时候基本功不扎实更容易遇到一些奇奇怪怪的坑。假设你不了解 ConcurrentHashMap 的 kv 不能为 null, 测试的时候没有覆盖这种场景等上线以后遇到这个问题可能直接导致线上问题甚至线上故障。 ConcurrentHashMap 作者在 put 方法注释中给出了 kv 不允许为 null 的提示并没有在注释中给出设计原因给众多读者带来了诸多困惑。这也给我们很大的启发当我们的某些设计容易引起别人的困惑和好奇时不仅要将注意事项放在注释中更应该将设计原因放在注释里避免给使用者带来困扰。 “适合自己的才是最好的”。正如不同的 Map 实现类各有千秋使用场景各有不同我们需要根据具体需求和场景进行权衡一样我们在设计方案时也会遇到类似的场景我们能做的是根据场景选择最适合的方案。 我们遇到的任何问题都是彻底掌握某个知识的绝佳机会。当我们遇到问题时应该主动掌握相关知识希望大家不仅能够知其然还要知其所以然。 创作不易如果本文对你有帮助欢迎点赞、收藏加关注你的支持和鼓励是我创作的最大动力。
http://www.hkea.cn/news/14469613/

相关文章:

  • 做网站找哪家好 07月云服务器使用教程
  • wordpress 专栏页面燕郊seo
  • 360网站收录网页制作在线生成
  • 云南公司网站制作建行网银登录
  • 仿搜狐视频网站源码黄金网软件app大全下载
  • 自己做网站要买服务器网站出现的的问题
  • wordpress 视频站模板下载失败赣州大余做网站建设
  • 做玩游戏任务得q币的网站网站按钮特效
  • 专业高端网站设计首选丽江市网站建设制作
  • 河北省住房与城乡建设厅网站郑州教育信息网
  • 建网站费用手机网站怎么布局
  • 网站开发设计师wordpress读法
  • 南京高端定制网站建设网站联盟名词解释
  • 那些空号检测网站是怎么做的设计一个自己的电商网站
  • 怎样保存网站资料 做证据无锡做网站价格
  • 做电商哪几个设计网站比较好招才猫网站多少钱做的
  • 足球比赛直播雨燕seo运营
  • 郑州市网站开发wordpress网站建设教程视频
  • 自己做的网站怎么放视频网站建设那家公司好
  • 网站收录说明cps推广联盟
  • 柳州市建设中心网站首页网站推广策划思路是什么
  • 石家庄网站建设seo公司哪家好网站 dns 解析
  • 如何学习网站建设app网店运营推广高级实训教程
  • 网站302怎么做资阳网站seo
  • wordpress修改网站菜单位置外贸soho东莞建站
  • 沙田网站仿做浙江住房和建设网站首页
  • 双语外贸网站源码空间一个数据库可以做几个网站
  • 聚民网网站建设谷歌网站怎么设置才能打开网站
  • 合肥网站建设与设计湖州 网站建设公司
  • 安防公司网站模板做网站的教程视频