返回介绍

4.3 LruCache.get(K key)

发布于 2024-12-23 21:09:29 字数 1786 浏览 0 评论 0 收藏 0

/**
 * 根据 key 查询缓存,如果存在于缓存或者被 create 方法创建了。
 * 如果值返回了,那么它将被移动到双向循环链表的的尾部。
 * 如果如果没有缓存的值,则返回 null。
 */
public final V get(K key) {

  ...  

  V mapValue;
  synchronized (this) {
    // 关键点:LinkedHashMap 每次 get 都会基于访问顺序来重整数据顺序
    mapValue = map.get(key);
    // 计算 命中次数
    if (mapValue != null) {
      hitCount++;
      return mapValue;
    }
    // 计算 丢失次数
    missCount++;
  }

  /*
   * 官方解释:
   * 尝试创建一个值,这可能需要很长时间,并且 Map 可能在 create() 返回的值时有所不同。如果在 create() 执行的时
   * 候,一个冲突的值被添加到 Map,我们在 Map 中删除这个值,释放被创造的值。
   */
  V createdValue = create(key);
  if (createdValue == null) {
    return null;
  }

  /***************************
   * 不覆写 create 方法走不到下面 *
   ***************************/

  /*
   * 正常情况走不到这里
   * 走到这里的话 说明 实现了自定义的 create(K key) 逻辑
   * 因为默认的 create(K key) 逻辑为 null
   */
  synchronized (this) {
    // 记录 create 的次数
    createCount++;
    // 将自定义 create 创建的值,放入 LinkedHashMap 中,如果 key 已经存在,会返回 之前相同 key 的值
    mapValue = map.put(key, createdValue);

    // 如果之前存在相同 key 的 value,即有冲突。
    if (mapValue != null) {
      /*
       * 有冲突
       * 所以 撤销 刚才的 操作
       * 将 之前相同 key 的值 重新放回去
       */
      map.put(key, mapValue);
    } else {
      // 拿到键值对,计算出在容量中的相对长度,然后加上
      size += safeSizeOf(key, createdValue);
    }
  }

  // 如果上面 判断出了 将要放入的值发生冲突
  if (mapValue != null) {
    /*
     * 刚才 create 的值被删除了,原来的 之前相同 key 的值被重新添加回去了
     * 告诉 自定义 的 entryRemoved 方法
     */
    entryRemoved(false, key, createdValue, mapValue);
    return mapValue;
  } else {
    // 上面 进行了 size += 操作 所以这里要重整长度
    trimToSize(maxSize);
    return createdValue;
  }
}

上述的 get 方法表面并没有看出哪里有实现了 LRU 的缓存策略。主要在 mapValue = map.get(key) ;里, 调用了 LinkedHashMap 的 get 方法,再加上 LruCache 构造里默认设置 LinkedHashMap 的 accessOrder=true

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文