linkedhashmap底层数据结构(linkedhashmap如何实现lru)

## LinkedHashMap底层数据结构

简介

LinkedHashMap是Java集合框架中的一种哈希表和链表的组合实现。它继承自HashMap,并额外维护了一个双向链表来记录元素的插入顺序。这意味着LinkedHashMap不仅可以提供HashMap的高效查找、插入和删除操作,还能保证元素的迭代顺序与插入顺序一致。 这使得LinkedHashMap在需要保持插入顺序的场景下非常有用,例如缓存实现。### 1. 数据结构组成LinkedHashMap的核心数据结构由两部分组成:

哈希表 (HashMap):

与HashMap一样,LinkedHashMap使用哈希表来存储键值对。哈希表使用数组+链表(或红黑树,取决于JDK版本和元素数量)的方式来解决哈希冲突。 这意味着键的查找时间复杂度在平均情况下为O(1),最坏情况下为O(n),其中n是桶中的元素数量。

双向链表 (Doubly Linked List):

LinkedHashMap 使用一个双向链表来维护元素的插入顺序。每个Entry(键值对)对象除了存储键值对本身外,还包含指向链表中前一个和后一个Entry的指针。链表的头结点指向最近插入的元素,尾结点指向最早插入的元素。### 2. Entry节点结构LinkedHashMap的内部类`Entry`继承自HashMap的`Node` (JDK 8及以后),包含以下关键字段:

`key`: 键

`value`: 值

`next`: 指向哈希表中下一个Entry的指针(用于处理哈希冲突)

`before`: 指向双向链表中前一个Entry的指针

`after`: 指向双向链表中后一个Entry的指针

`hash`: 键的哈希值### 3. 哈希冲突处理与HashMap类似,LinkedHashMap也需要处理哈希冲突。当多个键映射到同一个桶时,这些Entry会形成一个链表(或红黑树,在JDK 8及以后,当桶中元素数量超过TREEIFY_THRESHOLD时会转换为红黑树)。 链表的顺序取决于元素的插入顺序。### 4. 操作效率

查找 (get):

O(1) 平均时间复杂度,最坏情况O(n)

插入 (put):

O(1) 平均时间复杂度,最坏情况O(n)

删除 (remove):

O(1) 平均时间复杂度,最坏情况O(n)

迭代:

O(n),因为需要遍历链表### 5. 与HashMap和TreeMap的比较| 特性 | LinkedHashMap | HashMap | TreeMap | |-----------------|-----------------|---------------|---------------| | 元素顺序 | 保持插入顺序 | 无序 | 按键排序 | | 查找效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 插入效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 删除效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 适用场景 | 需要保持插入顺序的缓存、LRU缓存等 | 需要快速查找的场景 | 需要按键排序的场景 |### 6. 访问顺序控制 (accessOrder)LinkedHashMap 的构造函数允许指定一个布尔参数 `accessOrder`。

`accessOrder = false` (默认值): 迭代顺序保持插入顺序。

`accessOrder = true` : 迭代顺序保持访问顺序 (最近访问的元素排在前面)。 每次访问元素 (get操作),都会将该元素移动到链表的头部。 这使得LinkedHashMap可以很方便地实现LRU (Least Recently Used)缓存。

总结

LinkedHashMap 通过结合哈希表和双向链表,兼顾了HashMap的高效查找和链表保持元素顺序的能力。 理解其底层数据结构有助于更好地利用其特性,并在需要保持元素插入顺序或访问顺序的场景中做出最佳选择。

LinkedHashMap底层数据结构**简介**LinkedHashMap是Java集合框架中的一种哈希表和链表的组合实现。它继承自HashMap,并额外维护了一个双向链表来记录元素的插入顺序。这意味着LinkedHashMap不仅可以提供HashMap的高效查找、插入和删除操作,还能保证元素的迭代顺序与插入顺序一致。 这使得LinkedHashMap在需要保持插入顺序的场景下非常有用,例如缓存实现。

1. 数据结构组成LinkedHashMap的核心数据结构由两部分组成:* **哈希表 (HashMap):** 与HashMap一样,LinkedHashMap使用哈希表来存储键值对。哈希表使用数组+链表(或红黑树,取决于JDK版本和元素数量)的方式来解决哈希冲突。 这意味着键的查找时间复杂度在平均情况下为O(1),最坏情况下为O(n),其中n是桶中的元素数量。* **双向链表 (Doubly Linked List):** LinkedHashMap 使用一个双向链表来维护元素的插入顺序。每个Entry(键值对)对象除了存储键值对本身外,还包含指向链表中前一个和后一个Entry的指针。链表的头结点指向最近插入的元素,尾结点指向最早插入的元素。

2. Entry节点结构LinkedHashMap的内部类`Entry`继承自HashMap的`Node` (JDK 8及以后),包含以下关键字段:* `key`: 键 * `value`: 值 * `next`: 指向哈希表中下一个Entry的指针(用于处理哈希冲突) * `before`: 指向双向链表中前一个Entry的指针 * `after`: 指向双向链表中后一个Entry的指针 * `hash`: 键的哈希值

3. 哈希冲突处理与HashMap类似,LinkedHashMap也需要处理哈希冲突。当多个键映射到同一个桶时,这些Entry会形成一个链表(或红黑树,在JDK 8及以后,当桶中元素数量超过TREEIFY_THRESHOLD时会转换为红黑树)。 链表的顺序取决于元素的插入顺序。

4. 操作效率* **查找 (get):** O(1) 平均时间复杂度,最坏情况O(n) * **插入 (put):** O(1) 平均时间复杂度,最坏情况O(n) * **删除 (remove):** O(1) 平均时间复杂度,最坏情况O(n) * **迭代:** O(n),因为需要遍历链表

5. 与HashMap和TreeMap的比较| 特性 | LinkedHashMap | HashMap | TreeMap | |-----------------|-----------------|---------------|---------------| | 元素顺序 | 保持插入顺序 | 无序 | 按键排序 | | 查找效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 插入效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 删除效率 | O(1) 平均 | O(1) 平均 | O(log n) | | 适用场景 | 需要保持插入顺序的缓存、LRU缓存等 | 需要快速查找的场景 | 需要按键排序的场景 |

6. 访问顺序控制 (accessOrder)LinkedHashMap 的构造函数允许指定一个布尔参数 `accessOrder`。* `accessOrder = false` (默认值): 迭代顺序保持插入顺序。 * `accessOrder = true` : 迭代顺序保持访问顺序 (最近访问的元素排在前面)。 每次访问元素 (get操作),都会将该元素移动到链表的头部。 这使得LinkedHashMap可以很方便地实现LRU (Least Recently Used)缓存。**总结**LinkedHashMap 通过结合哈希表和双向链表,兼顾了HashMap的高效查找和链表保持元素顺序的能力。 理解其底层数据结构有助于更好地利用其特性,并在需要保持元素插入顺序或访问顺序的场景中做出最佳选择。

标签列表