双列集合---LinkedHashMap实现类

LinkedHashMap 是 Java 集合框架中的一个重要类,继承自 HashMap,并在其基础上增加了双向链表来维护元素的插入顺序或访问顺序,其实参考Set系列中LinkedHashSet就知道了,LinkedHashMap和HashMap不同的地方就在键值的存储数据结构是不一样,除了这点不同其他的完全一样;

其实这些集合的功能大同小异,只是底层实现的数据结构不同使得他们的用途不相同,但对于使用者来讲方法这没有什么不一样,只是他们适合的场合不同;


1. 特点

  1. 有序性
    • LinkedHashMap 保留了元素的插入顺序或访问顺序,这是它与 HashMap 的主要区别。
    • 默认按插入顺序排序,也可以配置为按访问顺序排序(最近访问的元素会排在最后)。
  1. 基于哈希表
    • 继承自 HashMap,底层仍然是哈希表,支持高效的查找、插入和删除操作,平均时间复杂度为 O(1)
  1. 双向链表
    • 通过双向链表维护元素的顺序,链表中的每个节点包含前驱和后继指针。
  1. 允许 null 键值
    • HashMap 一样,LinkedHashMap 允许键和值为 null
  1. 非线程安全
    • LinkedHashMap 不是线程安全的,多线程环境下需要额外同步。

2. 工作原理

  1. 哈希表
    • HashMap 相同,LinkedHashMap 通过哈希表存储键值对,使用哈希函数计算索引位置。
  1. 双向链表
    • 在哈希表的基础上,LinkedHashMap 增加了一个双向链表,用于维护元素的顺序。
    • 每个 Entry 节点(继承自 HashMap.Node)包含 beforeafter 指针,指向链表中的前驱和后继节点。
  1. 插入顺序
    • 默认情况下,新元素会添加到链表的末尾,保留插入顺序。
  1. 访问顺序
    • 如果 LinkedHashMap 配置为按访问顺序排序(通过构造函数 accessOrder=true),每次访问(调用 get()put())一个元素时,该元素会被移动到链表的末尾。

3. 常用方法

以下是 LinkedHashMap 中常用的方法:

方法签名

功能描述

V get(Object key)

根据键获取对应的值,未找到返回 null

V put(K key, V value)

添加键值对,如果键已存在则更新值。

V remove(Object key)

根据键删除键值对,返回被删除的值。

boolean containsKey(Object key)

判断是否包含指定键。

boolean containsValue(Object v)

判断是否包含指定值。

Set keySet()

返回所有键的集合。

Collection values()

返回所有值的集合。

Set> entrySet()

返回所有键值对的集合。

void clear()

清空所有键值对。

int size()

返回键值对的数量。


4. 使用示例

以下是一个简单的 LinkedHashMap 使用示例:

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapExample {
    public static void main(String[] args) {
        // 创建LinkedHashMap
        Map map = new LinkedHashMap<>();

        // 按插入顺序添加键值对
        map.put("Apple", 10);
        map.put("Banana", 5);
        map.put("Orange", 8);

        // 获取值
        System.out.println("Apple的库存: " + map.get("Apple")); // 输出: 10

        // 遍历键值对(按插入顺序)
        for (Map.Entry entry : map.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }
    }
}

5. 配置访问顺序

通过构造函数 accessOrder=true,可以将 LinkedHashMap 配置为按访问顺序排序:

Map map = new LinkedHashMap<>(16, 0.75f, true);
map.put("Apple", 10);
map.put("Banana", 5);
map.put("Orange", 8);

// 访问元素
map.get("Apple"); // 访问Apple
map.get("Banana"); // 访问Banana

// 遍历键值对(按访问顺序)
for (Map.Entry entry : map.entrySet()) {
    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
// 输出: Orange=8, Apple=10, Banana=5

6. 注意事项

  1. 内存开销
    • 由于维护双向链表,LinkedHashMap 的内存开销比 HashMap 更大。
  1. 线程安全问题
    • LinkedHashMap 不是线程安全的,多线程环境下需要额外同步,或使用 Collections.synchronizedMap() 包装。
  1. 适用场景
    • 需要保留插入顺序或访问顺序的场景,如实现 LRU 缓存。
  1. LRU 缓存实现
    • 通过重写 removeEldestEntry() 方法,可以实现一个固定大小的 LRU(最近最少使用)缓存。

7. 与 HashMap 的对比

特性

LinkedHashMap

HashMap

有序性

保留插入顺序或访问顺序

无序

底层实现

哈希表 + 双向链表

哈希表

内存开销

较大

较小

性能

略低于 HashMap

更高

适用场景

需要保留顺序的场景

快速查找、插入和删除


总结

LinkedHashMapHashMap 的扩展,通过双向链表实现了有序性。它适用于需要保留插入顺序或访问顺序的场景,如实现 LRU 缓存。理解其工作原理和配置方法,可以帮助开发者更好地在实际项目中应用 LinkedHashMap

你可能感兴趣的:(#,Java集合模块,java,开发语言,笔记)