LinkedHashMap底层结构

LinkedHashMap 是 Java 集合框架中 Map 接口的一个实现,它基于哈希表和双向链表来实现。LinkedHashMap 的特别之处在于,它不仅像普通的 HashMap 一样使用哈希表存储键值对,还维护了插入顺序或访问顺序的链表。这使得它可以保持元素的有序性,这与无序的 HashMap 形成对比。

1. LinkedHashMap 的基本特点

  • 有序性LinkedHashMap 保持键值对的顺序,这个顺序可以是插入顺序(默认)或访问顺序(可选)。这与 HashMap 不同,HashMap 无法保证任何顺序。
  • 底层实现LinkedHashMap 的实现基于 HashMap,但增加了双向链表来维护顺序。具体而言,每个节点在哈希表中存储数据时,不仅存储了键值对,还存储了指向前一个节点和后一个节点的引用。
  • 性能:与 HashMap 一样,LinkedHashMap 的基本操作(如插入、删除、查找等)都是 O(1) 的时间复杂度。然而,维护链表意味着在一定程度上增加了内存开销。

2. LinkedHashMap 的底层数据结构

LinkedHashMap 的底层结构是基于 HashMap 实现的,但它在 HashMap 的基础上添加了双向链表来维护顺序。这使得每个键值对不仅包含哈希表中的 Entry,还具有链表结构。

具体来说,它使用了 LinkedHashMap.Entry<K, V> 作为存储单元,这个类继承自 HashMap.Node<K, V>,并额外添加了两个指针 beforeafter,分别指向双向链表中的前一个和后一个节点。

static class Entry<K,V> extends HashMap.Node<K,V> {Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}
}
LinkedHashMap 的双向链表

每次插入元素时,不仅在哈希表中添加新节点,还要将其添加到链表的末尾。链表通过每个 Entrybeforeafter 指针进行链接:

  • before 指向前一个元素。
  • after 指向下一个元素。

这使得 LinkedHashMap 能够维护键值对的插入顺序。

3. LinkedHashMap 的工作原理

LinkedHashMap 的工作原理可以分为几个核心操作:插入元素、删除元素、访问元素和迭代元素。

插入元素

当向 LinkedHashMap 插入一个新的键值对时,底层的哈希表会先计算键的哈希值,并确定键值对存储在哈希表中的位置。与 HashMap 相同,LinkedHashMap 也会通过哈希冲突解决链(链地址法或红黑树)来管理冲突的键。

不同的是,每当插入新节点时,LinkedHashMap 会将新节点添加到链表的尾部。链表通过每个节点的 beforeafter 指针来维护插入顺序。

具体步骤如下:

  1. 计算哈希值,找到在哈希表中的位置。
  2. 如果该位置已有元素,采用链地址法解决冲突。
  3. 将新节点插入哈希表,同时更新链表,将新节点作为链表的最后一个节点。
删除元素

LinkedHashMap 删除元素的过程与 HashMap 基本相同。当删除一个键值对时,哈希表会通过哈希值定位到对应的桶,找到相应的节点并将其移除。

此外,LinkedHashMap 还需要更新双向链表的结构。具体来说,要将被删除节点的前后节点重新链接在一起,确保链表的完整性。假设要删除的节点是 e,它的前后节点分别是 beforeEafterE,删除后链表需要将 beforeEafter 指针指向 afterEafterEbefore 指针指向 beforeE

访问元素

LinkedHashMap 提供了一个可选的模式,即“访问顺序模式”。这种模式下,每当访问一个元素(即调用 getput 时获取已存在的元素),都会将该元素移动到链表的末尾。这意味着最近访问的元素会排在最后,从而形成一个按访问顺序排列的 LinkedHashMap

要启用访问顺序模式,只需在构造 LinkedHashMap 时将 accessOrder 设置为 true

LinkedHashMap<K, V> map = new LinkedHashMap<>(16, 0.75f, true);

默认情况下,accessOrderfalse,表示 LinkedHashMap 按插入顺序排列。

在访问顺序模式下,每次访问元素时,LinkedHashMap 都会将该元素移动到链表的末尾。这是通过重新链接链表实现的,即将访问的节点从链表中移除并重新插入到末尾。

迭代元素

由于 LinkedHashMap 维护了一个双向链表,它的迭代顺序与链表中的顺序一致。如果 LinkedHashMap 按插入顺序排列,那么迭代时将按插入顺序访问键值对。如果使用访问顺序排列,迭代顺序将按最近访问的顺序来访问。

4. LinkedHashMap 的其他特性

自定义删除策略

LinkedHashMap 提供了一个钩子方法 removeEldestEntry,允许用户自定义何时自动删除最老的元素。这在实现 LRU(最近最少使用)缓存时非常有用。removeEldestEntry 方法每次插入新元素时都会被调用,如果返回 true,则移除最老的元素。

示例:

LinkedHashMap<Integer, String> lruCache = new LinkedHashMap<Integer, String>(16, 0.75f, true) {@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {return size() > 5; // 限制缓存大小为 5}
};

在这个例子中,removeEldestEntry 方法控制了缓存的大小,当缓存超过 5 个元素时,最老的元素将被自动删除。

LRU 缓存实现

通过结合访问顺序和 removeEldestEntryLinkedHashMap 可以很容易地实现 LRU 缓存。每当访问一个元素时,该元素会被移动到链表的末尾,表示最近访问过的元素。而当元素过多时,通过 removeEldestEntry 来移除最不常使用的元素。

5. LinkedHashMapHashMap 的比较

  • 顺序性LinkedHashMap 保持元素的顺序(插入顺序或访问顺序),而 HashMap 不保证任何顺序。
  • 性能:由于 LinkedHashMap 维护了一个额外的双向链表,它的性能稍微比 HashMap 慢,但大多数情况下,其时间复杂度仍为 O(1)。
  • 内存开销LinkedHashMap 的每个节点不仅存储键值对,还存储两个额外的指针(beforeafter),因此它的内存开销比 HashMap 更大。

6. 适用场景

  • 缓存实现:由于 LinkedHashMap 支持按访问顺序排列,并且可以通过 removeEldestEntry 实现自动删除机制,因此它常用于实现 LRU 缓存。
  • 需要保持元素顺序的场景:在某些情况下,保持插入顺序是必须的,例如按顺序输出键值对、生成有序的报表等,这时 LinkedHashMap 是一个理想的选择。

总结

LinkedHashMap 通过结合哈希表和双向链表,提供了一种在保持高效查找、插入和删除操作的同时,维持键值对顺序的 Map 实现。它的底层结构基于 HashMap,但通过额外的链表维护了插入顺序或访问顺序。因此,它在需要有序性或实现 LRU 缓存时,是一个非常有用的数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1540160.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于YOLOv8/YOLOv9/YOLOv10的河道漂浮物检测识别系统

摘要&#xff1a; 河道漂浮物检测识别是指利用技术手段自动识别河流、湖泊等水体表面的漂浮垃圾或物体的过程。随着环境保护意识的增强和技术的进步&#xff0c;河道漂浮物检测已经成为水环境保护和管理的重要组成部分。这项技术的应用可以帮助及时发现污染源&#xff0c;采取措…

响应式监听localStorage存储?封装个自定义Hook不就好了!

背景 项目上有个更改时区的全局组件&#xff0c;同时还有一个可以更改时区的局部组件&#xff0c;想让更改时区的时候能联动起来&#xff0c;实时响应起来。 其实每次设置完时区的数据之后是存在了前端的 localStorage 里边&#xff0c;时&#xfffd;&#xfffd;&#xfff…

SaltStack的state定义主机状态及Jinja模版的使用

在前面我们学习了远程执行模块&#xff0c;这些模块的执行类似语段 she11 脚本&#xff0c;每次执行都会触发一次相同的功能&#xff0c;在大量的 minion 上运行远程命令当然是重要的&#xff0c;但是对于 minion 的环境控制&#xff0c;使用状态进行管理更为合适&#xff0c;转…

从零开始制作AI无人直播插件!

AI无人直播插件应运而生&#xff0c;它利用人工智能技术&#xff0c;实现了直播内容的自动化生成与播放&#xff0c;极大地降低了直播的人力成本和时间成本&#xff0c;本文将带你从零开始&#xff0c;探索如何制作一个AI无人直播插件&#xff0c;并分享五段关键的源代码。 AI…

谷歌深度学习研究揭示OpenAI O1模型优化策略:比规模更重要的计算效率

引言 近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;如OpenAI的GPT-4和Google DeepMind的Palm 2已成为自然语言处理领域的佼佼者&#xff0c;它们通过生成类人文本、回答复杂问题、编写代码等能力&#xff0c;改变了许多行业的工作方式。然而&#xff0c;随着这…

IO流体系(FiletOutputStream)

书写步骤&#xff1a; 1.创建字节输出流对象 细节1:参数是字符串表示的路径或者是File对象都是可以的 细节2:如果文件不存在会创建一个新的文件&#xff0c;但是要保证父级路径是存在的。 细节3:如果文件已经存在&#xff0c;则会清空文件 2.写数据 细节:write方法的参数…

大白话解读末日期权是什么意思?末日期权与黑天鹅!

今天带你了解大白话解读末日期权是什么意思&#xff1f;末日期权与黑天鹅&#xff01;末日期权与黑天鹅事件的关系主要体现在风险和波动性管理上&#xff0c;交易者需要谨慎对待这两者的互动。 末日期权和期权黑天鹅事件之间的关系主要体现在风险管理和市场波动性上。 末日期…

没有那个文件或目录 #include <bits/libc-header-start.h>

Ubuntu 18.04 编译需要编译32位系统 gcc -ggdb -m32 -c -o exploit.o exploit.c gcc -m32 -L/usr/lib32 exploit.o -o exploit 报错&#xff1a; 解决方法&#xff1a; sudo apt-get install libc6-dev-i386sudo apt-get install gcc-multilib

【C++】哈希表:字母异位词分组(体会泛型编程的强大)

1.题目 2.思路 利用map的特性&#xff0c;第一个值存排好序的string&#xff0c;第二个值存vector<string>。这样就可以很好的将异位词分组。 3.代码 class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {un…

25届计算机专业毕设选题推荐-基于python的二手电子设备交易平台【源码+文档+讲解】

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于python的二手电子设备交…

六西格玛绿带培训多少钱?从授“鱼”到授“渔”

六西格玛作为一种全球公认的质量管理方法&#xff0c;其影响力日益扩大&#xff0c;而六西格玛绿带培训作为这一体系中的关键环节&#xff0c;更是吸引了众多希望在职场上脱颖而出的专业人士。本文&#xff0c;深圳天行健企业管理咨询公司将从多个维度深入探讨“六西格玛绿带培…

【大模型】初识大模型(非常详细)零基础入门到精通,收藏这一篇就够了_大模型入门

大模型的定义 大模型是指具有数千万甚至数亿参数的深度学习模型。近年来&#xff0c;随着计算机技术和大数据的快速发展&#xff0c;深度学习在各个领域取得了显著的成果&#xff0c;如自然语言处理&#xff0c;图片生成&#xff0c;工业数字化等。为了提高模型的性能&#xf…

游戏如何应对云手机刷量问题

云手机的实现原理是依托公有云和 ARM 虚拟化技术&#xff0c;为用户在云端提供一个安卓实例&#xff0c;用户可以将手机上的应用上传至云端&#xff0c;再通过视频流的方式&#xff0c;远程实时控制云手机。 市面上常见的几款云手机 原本需要手机提供的计算、存储等能力都改由…

在校三个月备考软考中项顺利拿证,经验分享

作为一名在校生&#xff0c;我在三个月的备考软考中项后成功拿到证书&#xff0c;对于软考中项的考试技巧有着丰富的经验。首先&#xff0c;我给你分享一些备考技巧&#xff1a; 1. 不要死记硬背&#xff01;最好是结合跟班学习和教材双管齐下。先过一遍所有知识点&#xff08…

如何查看Android设备的dpi

adb shell getprop ro.sf.lcd_density adb shell cat /system/build.prop > build_prop.txt shell cat system/build.prop 结果&#xff1a;参考&#xff1a; 如何查看Android设备的dpi_安卓 查看手机dpi-CSDN博客

【里程碑】轻空间SPIKE AIRDOME项目落地印尼雅加达

在经过半年的激烈角逐与严苛考量后&#xff0c;轻空间凭借其卓越的气承式球幕技术&#xff0c;成功赢得印尼最大城市建设商的青睐&#xff0c;正式签约 SPIKE AIRDOME 项目。该项目将落地印尼首都雅加达CBD&#xff0c;成为这一繁华商业中心的全新地标。轻空间技术负责人亲切地…

一些线上常用排查问题的命令

排查CPU过高时使用到的一些命令 top free df top命令 top 命令是一个动态的实时视图&#xff0c;显示系统的整体运行状况&#xff0c;包括 CPU 使用率、内存使用情况、进程信息等。 free 命令 free 命令用于显示系统中物理内存和交换内存的使用情况。 df 命令 df 命令用…

如何从 Nutanix 迁移至 SmartX 超融合?解读 4 类迁移方案和 2 例迁移实践

2022 年底&#xff0c;Nutanix&#xff08;路坦力&#xff09;正式宣布将中国市场交由合作伙伴&#xff08;联想&#xff09;主导销售&#xff0c;并于 2023 年 8 月完成全面转型。转型后&#xff0c;虽然中国用户依旧可以使用 Nutanix 产品&#xff0c;但在软件的续保和维保方…

基于flask+vue框架的传染病防控酒店信息系统zvt93(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;患者,服务人员,病房类型,病房信息,病房分配,需求箱,商品分类,商品信息,购买商品,分配反馈,健康上报,患者信息,患者分配 开题报告内容 基于flaskvue框架的传染病防控酒店信息系统开题报告 一、项目背景 在全球公共卫生事件频发的背景下…

鸿蒙应用生态构建的核心目标

保护开发者和用户利益的同时维护整体系统的安全性&#xff0c;对生态构建者是至关重要的。以开发者为中心&#xff0c;构建端到端应用安全能力&#xff0c;保护应用自身安全、运行时安全&#xff0c;保障开发者权益&#xff0c;是鸿蒙应用生态构建的核心目标。 应用生命周期主要…