JavaScript实现LRU缓存的三种方式详解

JavaScript实现LRU缓存的三种方式详解

LRU(Least Recently Used)缓存是一种常用的缓存算法,它根据数据的访问时间来决定哪些数据应该被保留,哪些数据应该被淘汰。在JavaScript中,可以使用以下三种方式来实现LRU缓存。

方式一:使用Map和双向链表实现LRU缓存

以下是使用Map和双向链表实现LRU缓存的示例代码:

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.map = new Map();
    this.head = null;
    this.tail = null;
  }

  get(key) {
    if (!this.map.has(key)) {
      return -1;
    }
    const value = this.map.get(key).value;
    this.removeNode(this.map.get(key));
    this.addNode(new Node(key, value));
    return value;
  }

  put(key, value) {
    if (this.map.has(key)) {
      this.removeNode(this.map.get(key));
    }
    const node = new Node(key, value);
    this.addNode(node);
    this.map.set(key, node);
    if (this.map.size > this.capacity) {
      this.map.delete(this.tail.key);
      this.removeNode(this.tail);
    }
  }

  addNode(node) {
    if (this.head === null) {
      this.head = node;
      this.tail = node;
    } else {
      node.next = this.head;
      this.head.prev = node;
      this.head = node;
    }
  }

  removeNode(node) {
    if (node === this.head) {
      this.head = node.next;
      if (this.head !== null) {
        this.head.prev = null;
      }
    } else if (node === this.tail) {
      this.tail = node.prev;
      if (this.tail !== null) {
        this.tail.next = null;
      }
    } else {
      node.prev.next = node.next;
      node.next.prev = node.prev;
    }
  }
}

class Node {
  constructor(key, value) {
    this.key = key;
    this.value = value;
    this.prev = null;
    this.next = null;
  }
}

上述代码中,使用Map来存储缓存数据,使用双向链表来维护缓存数据的访问顺序。当访问缓存数据时,先从Map中获取数据,然后将该节点移动到链表头部。当添加新的缓存数据时,先判断Map中是否已经存在该数据,如果存在,则将该节点移动到链表头部,否则添加新的节点到链表头部,并将该节点添加到Map中。当缓存数据超过容量时,删除链表尾部的节点,并从Map中删除该节点。

方式二:使用ES6 Map和Proxy实现LRU缓存

以下是使用ES6 Map和Proxy实现LRU缓存的示例代码:

function createLRUCache(capacity) {
  const cache = new Map();
  return new Proxy(cache, {
    get(target, key) {
      if (target.has(key)) {
        const value = target.get(key);
        target.delete(key);
        target.set(key, value);
        return value;
      }
      return -1;
    },
    set(target, key, value) {
      if (target.has(key)) {
        target.delete(key);
      }
      target.set(key, value);
      if (target.size > capacity) {
        target.delete(target.keys().next().value);
      }
      return true;
    },
  });
}

上述代码中,使用ES6 Map来存储缓存数据,使用Proxy来拦截对Map的访问。当访问缓存数据时,先从Map中获取数据,然后将该节点移动到Map的末尾。当添加新的缓存数据时,先判断Map中是否已经存在该数据,如果存在,则将该节点移动到Map的末尾,否则添加新的节点到Map的末尾。当缓存数据超过容量时,删除Map中第一个节点。

方式三:使用ES6 Map和Symbol实现LRU缓存

以下是使用ES6 Map和Symbol实现LRU缓存的示例代码:

const LRUCache = function (capacity) {
  this.capacity = capacity;
  this.map = new Map();
  this.keys = [];
};

LRUCache.prototype.get = function (key) {
  if (!this.map.has(key)) {
    return -1;
  }
  const value = this.map.get(key);
  this.keys.splice(this.keys.indexOf(key), 1);
  this.keys.push(key);
  return value;
};

LRUCache.prototype.put = function (key, value) {
  if (this.map.has(key)) {
    this.keys.splice(this.keys.indexOf(key), 1);
  }
  this.keys.push(key);
  this.map.set(key, value);
  if (this.keys.length > this.capacity) {
    const firstKey = this.keys.shift();
    this.map.delete(firstKey);
  }
};

上述代码中,使用ES6 Map来存储缓存数据,使用Symbol来存储缓存数据的访问顺序。当访问缓存数据时,先从Map中获取数据,然后将该节点移动到Symbol对应的数组的末尾。当添加新的缓存数据时,先判断Map中是否已经存在该数据,如果存在,则将该节点移动到Symbol对应的数组的末尾,否则添加新的节点到Symbol对应的数组的末尾。当缓存数据超过容量时,删除Symbol对应的数组的第一个节点,并从Map中删除该节点。

总结

本文介绍了JavaScript实现LRU缓存的三种方式,包括使用Map和双向链表、ES6 Map和Proxy以及ES6 Map和Symbol等方式。了解这些内容可以帮助我们更好地使用LRU缓存算法来提高应用程序的性能和响应速度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript实现LRU缓存的三种方式详解 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • Java进程内缓存框架EhCache详解

    Java进程内缓存框架EhCache详解 EhCache是一个Java进程内缓存框架,它提供了快速、可扩展、易于使用的缓存解决方案。本攻略将详细讲解EhCache的使用方法,包括缓存的创建、读取、更新和删除,以及缓存的失效策略和缓存的持久化等方面,并提供两个示例说明。 创建缓存 要创建一个缓存,我们需要使用EhCache的CacheManager类。Cach…

    缓存 2023年5月18日
    00
  • 2021年最新Redis面试题汇总(4)

    下面是对“2021年最新Redis面试题汇总(4)”的详细讲解。 2021年最新Redis面试题汇总(4) 1. Redis的高并发解决方案有哪些? 缓存穿透:可以使用Bloom Filter(布隆过滤器)和缓存空对象两种方法解决。 Bloom Filter:一种数据结构,可以判断一个元素是否存在于一个大集合中,具有高效、低存储、低错误率的特点。使用Bloo…

    缓存 2023年5月16日
    00
  • mysql缓冲和缓存设置详解

    MySQL缓冲和缓存设置详解 MySQL缓冲和缓存设置是MySQL数据库优化的重要方面。通过合理设置缓冲和缓存,可以提高MySQL数据库的性能和响应速度。本文将详细介绍MySQL缓冲和缓存设置的相关知识。 MySQL缓冲 MySQL缓冲是指MySQL服务器在内存中缓存数据和索引,以提高数据访问速度和性能。MySQL缓冲主要包括以下几种类型: 查询缓存 查询缓…

    缓存 2023年5月18日
    00
  • Redis与本地缓存的结合实现

    Redis与本地缓存的结合实现 Redis是一种流行的内存数据库,它提供了一种方便的方式来缓存数据。本攻略将详细讲解Redis与本地缓存的结合实现的原理、使用方法和示例。 Redis与本地缓存的结合实现的原理 Redis与本地缓存的结合实现的原理是将数据缓存到Redis中,并使用本地缓存来提高数据的访问速度和性能。Redis与本地缓存的结合实现主要有以下两种…

    缓存 2023年5月18日
    00
  • PHP微信开发用Cache 解决数据缓存

    PHP微信开发用Cache解决数据缓存 在PHP微信开发中,为了提高应用程序的性能,可以使用缓存来减少数据库的访问次数。PHP提供了多种缓存方式,其中之一是使用Cache来实现数据缓存。下面是一个使用Cache解决数据缓存的完整攻略: 示例一:配置文件 在PHP中,可以使用php.ini文件来配置Cache。下面是一个示例: [Session] sessio…

    缓存 2023年5月18日
    00
  • 手机搜狐视频缓存的视频在哪里?如何查看

    当使用手机搜狐视频观看视频时,经常会出现视频卡顿的情况。为了更好地解决这个问题,很多人都会选择将视频缓存到自己的手机中。那么,缓存的视频具体在哪里呢?如何查看这些视频呢? 一. 手机搜狐视频缓存的视频在哪里? 手机搜狐视频缓存的视频实际上是存储在手机的相应文件夹中的。而这个文件夹的具体位置则因不同的手机而异。以下是两个示例: 1. 华为手机 华为手机的搜狐视…

    缓存 2023年5月16日
    00
  • Mybatis详细对比一级缓存与二级缓存

    Mybatis详细对比一级缓存与二级缓存 Mybatis是一种流行的Java持久化框架,它提供了一级缓存和二级缓存来提高应用程序的性能和响应速度。在本文中,我们将详细对比一级缓存和二级缓存。 一级缓存 一级缓存是Mybatis默认开启的缓存,它是基于SqlSession的缓存。一级缓存的作用域是SqlSession,当SqlSession关闭时,一级缓存也会…

    缓存 2023年5月18日
    00
  • 安卓手机怎么清理缓存 android清除程序缓存的方法

    在使用安卓手机的过程中,缓存会逐渐积累,占用手机存储空间,影响手机的性能和响应速度。本攻略将详细讲解如何清理安卓手机的缓存,包括清除程序缓存的方法和清除系统缓存的方法,并提供两个示例说明。 清除程序缓存的方法 清除程序缓存是指清除应用程序在手机中缓存的数据。我们可以按照以下步骤来清除程序缓存: 打开“设置”应用程序。 选择“应用和通知”选项。 在“应用和通知…

    缓存 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部