千家信息网

如何深入解读LinkedHashMap原理和源码

发表于:2025-02-08 作者:千家信息网编辑
千家信息网最后更新 2025年02月08日,如何深入解读LinkedHashMap原理和源码,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。LinkedHashMap 顾名思义,就是
千家信息网最后更新 2025年02月08日如何深入解读LinkedHashMap原理和源码

如何深入解读LinkedHashMap原理和源码,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

LinkedHashMap 顾名思义,就是一个基于 HashMap 的双向链表的集合。其中 HashMap 为数组加单向链表的结构,LinkedList 为双向链表实现的。而 LinkedHashMap 正是二者的结合体。

首先,从源码上来看,LinkedHashMap 继承自 HashMap,所以 HashMap 有的大部分特性,LinkedHashMap 都有。比如:线程安全问题等。关于 HashMap 推荐阅读《搞不懂 HashMap?只因你缺一个 HashMap 的原理机制流程图!》。

顺着 LinkedHashMap 的源码往下看,你会发现 LinkedHashMap 提供了 5 个构造函数。基本上就是对 HashMap 的构造函数做了扩展,加了一个重要的参数 accessOrder,它代表的是一个访问顺序,后面会具体的讲。

注意上图,LinkedHashMap 还有一个改变就是多了两个属性:header 和 accessOrder。header 就是双向链表的表头元素。当 accessOrder 为 true 时,代表按访问顺序迭代,false 时表示按照插入顺序。这个配图来自网上,是基于 JDK1.6 的,现在 JDK8 的变化已经很大了。

LinkedHashMap 继承了 HashMap 中大部分的方法,只是多了双向链表。

LinkedHashMap 的 Entry 增加了用于维护顺序的 before 和 after 变量,就是用来确定链表的前后节点。本来无序的数组 + 链表结构,通过 before 和 after 把它们关联起来,变的有序。在 put 和 get 的时候维护好了这个双向链表,遍历的时候就有序了。

LinkedHashMap 的节点 Entry 继承自 HashMap.Node,然后将单向链表改成了一个双向链表。

LinkedHashMap 并没有重写任何 put 方法。但是其重写了构建新节点的 newNode() 方法。
newNode() 会在 HashMap 的 putVal() 方法里被调用,putVal() 方法会在批量插入数据 putMapEntries(Map m, boolean evict) 或者插入单个数据 public V put(K key, V value) 时被调用。

LinkedHashMap 重写了 newNode(),在每次构建新节点时,通过 linkNodeLast(p); 将新节点链接在内部双向链表的尾部。

其中的 linkNodeLast 方法,会将新增的节点。如果,集合之前是空的,指定 head 节点;否则将新节点连接在链表的尾部。

另外 LinkedHashMap 的 afterNodeInsertion 方法也非常的重要,它会在新节点插入之后回调,根据 evict 和 first 判断是否需要删除最老插入的节点。

LinkedHashMap 还重写了 afterNodeRemoval 这个方法。在删除节点 e 时,同步将 e 从双向链表上删除。

另外 get() 和 getOrDefault() 方法也被重写了。因为我们要根据 accessOrder 规则来调整具体的获取方法。在 accessOrder 为 true 的情况下,要去回调 void afterNodeAccess(Node e) 函数。

在 afterNodeAccess() 函数中,会将当前被访问到的节点 e,移动至内部的双向链表的尾部。

通过上图的解释,你会发现。afterNodeAccess 方法埋下了隐患,会修改 modCount,因此当你正在 accessOrder=true 的模式下,迭代 LinkedHashMap 时,如果同时查询访问数据,也会导致 fail-fast,因为迭代的顺序已经改变。

最后,总结一下。LinkedHashMap 相对于 HashMap 的源码比,是很简单的。因为大树底下好乘凉。它继承了 HashMap,仅重写了几个方法,以改变它迭代遍历时的顺序。这也是其与 HashMap 相比最大的不同。在每次插入数据,或者访问、修改数据时,会增加节点、或调整链表的节点顺序。以决定迭代时输出的顺序。

  • accessOrder,默认是 false,则迭代时输出的顺序是插入节点的顺序。

    若为 true,则输出的顺序是按照访问节点的顺序。

    为 true 时,可以在这基础之上构建一个 LruCache。

    参考《手把手教你用LinkedHashMap打造FIFO和LRU缓存系统》

  • LinkedHashMap 并没有重写任何 put 方法。

    但是其重写了构建新节点的 newNode() 方法.在每次构建新节点时,将新节点链接在内部双向链表的尾部

  • accessOrder=true 的模式下,在 afterNodeAccess() 函数中,会将当前被访问到的节点 e,移动至内部的双向链表的尾部。

    值得注意的是,afterNodeAccess() 函数中,会修改 modCount,因此当你正在 accessOrder=true 的模式下,迭代 LinkedHashMap 时,如果同时查询访问数据,也会导致 fail-fast,因为迭代的顺序已经改变。


  • nextNode() 就是迭代器里的next()方法。

    该方法的实现可以看出,迭代 LinkedHashMap,就是从内部维护的双链表的表头开始循环输出。

    而双链表节点的顺序在LinkedHashMap的增、删、改、查时都会更新。

    以满足按照插入顺序输出,还是访问顺序输出。


  • 它与 HashMap 比,还有一个小小的优化,重写了 containsValue() 方法,直接遍历内部链表去比对 value 值是否相等。

看完上述内容,你们掌握如何深入解读LinkedHashMap原理和源码的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

节点 方法 顺序 双向 迭代 函数 就是 数据 输出 源码 尾部 原理 模式 问题 有序 重要 上图 代表 内容 单向 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海运营网络技术收费 邮件代理服务器之间用什么协议 牌匾设计软件开发 华为防火墙配置服务器日志 北京移动软件开发价格 天涯明月刀手游出新服务器时间段 数据库修改主键值 发票报送中服务器返回信息错误 中国互联网高科技未来 培训的软件开发工作发现不适合 超星百万测试二次文献数据库 麦田网络技术有限公司 阿帕虎题库管理系统服务器 郑州程序软件开发大概要多少钱 计算机网络技术这个技术好学吗 互联网科技智慧城 超频三铁塔服务器散热器 冒险岛2和服务器断开 自考计算机网络技术 填空题 睿名互联网科技有限公司 幻塔为什么总连不上服务器 组装服务器电源教程 sql注入判断数据库列数 网络技术服务工作方案 学校需要什么网络技术 aws ftp服务器 csgo怎样进国服服务器 A HCI是全文型数据库吗 vssql怎么添加数据库 青少年网络安全活动图片
0