【Java】LinkedHashMap (LRU)淘汰缓存的使用

文章目录

      • [**1. `initialCapacity`(初始容量)**](#1. initialCapacity(初始容量))
      • [**2. `loadFactor`(加载因子)**](#2. loadFactor(加载因子))
      • [**3. `accessOrder`(访问顺序)**](#3. accessOrder(访问顺序))
      • **完整参数解释示例**
      • **示例验证**

LinkedHashMap 在 Java 中可维护元素插入或访问顺序,并实现 LRU 缓存,适用于有序存储数据和缓存管理场景。

在 Java 中,LinkedHashMap 的构造函数可以接受三个参数,分别是 initialCapacityloadFactoraccessOrder。以下是具体含义:


1. initialCapacity(初始容量)

  • 含义 :指定 LinkedHashMap 的初始容量,也就是可以存储的键值对的数量。
  • 默认值 :默认初始容量是 16
  • 工作机制 :当存储的键值对数量超过容量的 loadFactor 阈值时,LinkedHashMap 会自动扩容。
  • 设置建议:如果预估可以存储的键值对数量,可以设置为大于等于预估值。否则,系统在达到阈值时会进行扩容,可能影响性能。

示例

java 复制代码
new LinkedHashMap<>(16, 0.75f, true); // 初始容量为 16

2. loadFactor(加载因子)

  • 含义 :定义 LinkedHashMap 的扩容触发条件,计算公式为: 扩容阈值=initialCapacity×loadFactor\text{扩容阈值} = \text{initialCapacity} \times \text{loadFactor}
  • 默认值0.75
  • 工作机制 :当存储的键值对数量超过扩容阈值时,LinkedHashMap 会将容量增加一倍(重新哈希)。
  • 设置建议
    • 较低的加载因子(如 0.5):减少冲突,但会增加内存占用。
    • 较高的加载因子(如 1.0):节省内存,但会增加冲突概率,影响性能。

示例

java 复制代码
new LinkedHashMap<>(16, 0.75f, true); // 加载因子为 0.75,扩容阈值为 16 × 0.75 = 12

3. accessOrder(访问顺序)

  • 含义 :定义键值对的迭代顺序:
    • false(默认值):按照插入顺序排序(插入顺序)。
    • true:按照访问顺序排序(最近访问的在后面)。
  • 工作机制 :如果 accessOrder 设置为 true,每次访问(包括 getput 操作)会将该键值对移动到双向链表的尾部,从而保证最近访问的元素总是位于链表末尾。
  • 使用场景
    • 如果需要实现 LRU 缓存 (Least Recently Used),设置 accessOrder = true
    • 如果不需要按访问顺序排序,可以省略该参数或设置为 false

示例

java 复制代码
new LinkedHashMap<>(16, 0.75f, true); // 按访问顺序排序

完整参数解释示例

java 复制代码
LinkedHashMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
  1. initialCapacity = 16:初始可以存储最多 16 个键值对。
  2. loadFactor = 0.75f:扩容阈值为 16×0.75=1216 \times 0.75 = 12,当存储键值对超过 12 时触发扩容。
  3. accessOrder = true:按访问顺序排序,最近访问的键值对会移动到链表末尾。

示例验证

以下代码展示了 accessOrder = true 的效果:

java 复制代码
import java.util.LinkedHashMap;
import java.util.Map;

public class AccessOrderTest {
    public static void main(String[] args) {
        Map<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);

        map.put("A", 1);
        map.put("B", 2);
        map.put("C", 3);

        System.out.println("Initial: " + map);

        // 访问 "A"
        map.get("A");
        System.out.println("After accessing A: " + map);

        // 插入新元素 "D"
        map.put("D", 4);
        System.out.println("After inserting D: " + map);
    }
}

输出结果

Initial: {A=1, B=2, C=3}
After accessing A: {B=2, C=3, A=1}
After inserting D: {B=2, C=3, A=1, D=4}

解释

  • 初始状态:A -> B -> C,按照插入顺序。
  • 访问 A 后:B -> C -> AA 被移到链表末尾。
  • 插入 D 后:B -> C -> A -> D,新键值对始终追加到尾部。

相关推荐
bing_1585 分钟前
Redis动态热点数据缓存策略设计
redis·spring·缓存
青木川崎14 分钟前
java集合面试题
java·windows·面试
hakesashou21 分钟前
python如何设计矩阵
开发语言·python·矩阵
敖行客 Allthinker22 分钟前
Ruby JSON 优化之路:性能提升的探索与实践
开发语言·json·ruby
工业甲酰苯胺30 分钟前
.NET8.0多线程编码结合异步编码示例
java·算法·.net
lly2024061 小时前
PHP Filesystem
开发语言
lly2024061 小时前
PHP 字符串
开发语言
Java知识日历1 小时前
Springboot集成Easy Rules引擎,实现一个商品优惠券系统
java·spring boot·后端·spring
Java知识日历1 小时前
SpringBoot整合Grizzly,提高您网站的并发能力
java·spring boot·后端·spring
Allen Bright1 小时前
【JVM-7】JVM 命令行工具 jstack 的使用和具体应用案例
java·开发语言·jvm