欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用JavaScript實現(xiàn)LRU緩存的代碼詳解

 更新時間:2024年05月21日 11:20:31   作者:隱藏用戶_y  
LRU(Least?Recently?Used)算法是一種廣泛應用于內存管理和緩存系統(tǒng)的策略,本文將介紹LRU算法的基本原理,并通過JavaScript實現(xiàn)案例,幫助讀者理解其在前端開發(fā)中的應用場景,需要的朋友可以參考下

引言

LRU(Least Recently Used)算法是一種廣泛應用于內存管理和緩存系統(tǒng)的策略,在微前端、狀態(tài)管理以及性能優(yōu)化等場景下,合理使用緩存機制能夠有效提升應用性能。本文將介紹LRU算法的基本原理,并通過JavaScript實現(xiàn)案例,幫助讀者理解其在前端開發(fā)中的應用場景。

LRU算法原理

LRU(最近最少使用)算法是一種常用的緩存淘汰策略,它假定“最近最久未使用的數(shù)據在未來被訪問的可能性最小”。當緩存空間不足時,LRU會優(yōu)先移除最近最少使用的數(shù)據,為新數(shù)據騰出存儲空間。

實現(xiàn)方式

哈希表適合快速查找、插入和刪除的場景,而雙向鏈表適合頻繁插入和刪除節(jié)點的場景。在某些情況下,這兩種數(shù)據結構也可以結合實現(xiàn)LRU緩存算法時,可以使用哈希表存儲 key 和對應的節(jié)點,雙向鏈表存儲實際的數(shù)據節(jié)點,以實現(xiàn)快速的查找和插入刪除操作。

圖解示例

假設設計一個容量為3的LRU緩存

首先添加3個元素

哈希表中依次添加數(shù)據的key值:key1,key2,key3

雙向鏈表存儲哈希對(key,value),key3是最后一個添加的(最新添加記錄是key3),那么key3對應的哈希值添加到鏈表的頭部node3。表示最近使用的。

這個時候如果要添加第四個數(shù)據,key4放入哈希表,node4放入雙向鏈表頭部,node4包含key4,value4,然而此時容量不足,需要刪除一個元素,從尾部刪除一個最久沒使用的元素,刪除上面圖示中的node1的數(shù)據,同時在哈希表中刪除node1對應的key1 把node4添加到鏈表頭部,key4添加進哈希表是同步進行的。

如果最近要訪問key3,需要把node3從當前位置刪除,并插入到鏈表頭部

簡而言之:

每次添加元素到鏈表中的時候都是從頭部添加

每次刪除元素的時候都是從尾部刪除

刪除的時候同時從哈希表里面刪除對應的key

再次訪問的元素,需要把元素移動到鏈表的頭部

實現(xiàn)代碼

使用哈希鏈表,可以在每個緩存項的節(jié)點上同時存儲鍵值信息以及指向鏈表中前后節(jié)點的引用。當一個緩存項被訪問時,先通過哈希表找到對應節(jié)點,然后將其從原有位置移出并插入鏈表尾部

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


class LRUCache {
  constructor(capacity = 500) {
    this.capacity = capacity;
    this.cacheMap = new Map(); // 使用哈希表存儲鍵值對
    this.doubleLinkedList = new DoublyLinkedList(); // 雙向鏈表維護緩存順序
  }

  get(key) {
    if (this.cacheMap.has(key)) {
      const node = this.cacheMap.get(key);
      this.doubleLinkedList.moveToTail(node); // 將節(jié)點移動到鏈表尾部,表示最新訪問
      return node.value;
    }
    return -1; // 或者返回null,表示key不存在于緩存中
  }

  put(key, value) {
    if (this.cacheMap.has(key)) {
      const node = this.cacheMap.get(key);
      node.value = value;
      this.doubleLinkedList.moveToTail(node);
    } else {
      if (this.cacheMap.size >= this.capacity) {
        const headNode = this.doubleLinkedList.deleteHead();
        this.cacheMap.delete(headNode.key); // 移除最舊的緩存項
      }
      const newNode = new Node(key, value);
      this.cacheMap.set(key, newNode);
      this.doubleLinkedList.addToTail(newNode);
    }
  }
}

// 雙向鏈表類和節(jié)點類的實現(xiàn)略(根據實際需求實現(xiàn))
class Node {
  constructor(key, value) {
    this.key = key; // 節(jié)點鍵值
    this.value = value; // 節(jié)點數(shù)據值
    this.prev = null; // 前驅節(jié)點引用
    this.next = null; // 后繼節(jié)點引用
  }
}
class DoublyLinkedList {
  constructor() {
    this.head = null; // 頭節(jié)點
    this.tail = null; // 尾節(jié)點
  }

  /**
   * 添加節(jié)點到鏈表尾部
   * @param {Node} newNode 新節(jié)點
   */
  addToTail(newNode) {
    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.prev = this.tail;
      this.tail.next = newNode;
      this.tail = newNode;
    }
  }

  /**
   * 移除頭節(jié)點并返回
   * @returns {Node | null} 刪除的頭節(jié)點或null(如果鏈表為空)
   */
  deleteHead() {
    if (!this.head) return null;

    const deletedNode = this.head;
    this.head = this.head.next;

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

    return deletedNode;
  }

  /**
   * 將指定節(jié)點移動到鏈表尾部
   * @param {Node} node 需要移動的節(jié)點
   */
  moveToTail(node) {
    if (node === this.tail) return; // 如果已經是尾節(jié)點,則無需移動

    // 斷開當前節(jié)點與前后節(jié)點的連接
    node.prev.next = node.next;
    if (node.next) node.next.prev = node.prev;

    // 將節(jié)點添加至鏈表尾部
    this.addToTail(node);
  }
  
  // 其他可能的方法,如查找節(jié)點、在指定位置插入節(jié)點等...
}


使用場景

路由緩存

Vue.js 中的 keep-alive 組件雖然并未直接采用LRU算法,但在實際項目中,我們可以基于LRU策略自定義實現(xiàn)路由組件的緩存功能。

資源加載

對于頻繁請求且響應較慢的API,可以通過LRU緩存最近請求的結果,減少網絡請求次數(shù)。

狀態(tài)管理

在Vuex或Redux等狀態(tài)管理庫中,也可以利用LRU算法進行緩存,避免頻繁計算或獲取昂貴的狀態(tài)。

業(yè)務場景

電商大促,瀏覽器瀏覽歷史,微博熱點。實現(xiàn)的具體可能不同,但是思路均可使用LRU緩存實現(xiàn).

網頁瀏覽歷史

實現(xiàn)一個簡單的瀏覽歷史記錄功能

class LRUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.cache = new Map();
    }

    get(key) {
        if (this.cache.has(key)) {
            const value = this.cache.get(key);
            // 刪除舊數(shù)據再重新插入,以更新最近訪問的順序
            this.cache.delete(key);
            this.cache.set(key, value);
            return value;
        }
        return null;
    }

    put(key, value) {
        if (this.cache.has(key)) {
            this.cache.delete(key);
        } else if (this.cache.size >= this.capacity) {
            // 超出容量時刪除最久未訪問的數(shù)據(即最近使用頻率最低的數(shù)據)
            const keys = this.cache.keys();
            this.cache.delete(keys.next().value);
        }
        this.cache.set(key, value);
    }

    displayHistory() {
        console.log("Browser History:");
        for (let [key, value] of this.cache) {
            console.log(key + " -> " + value);
        }
    }
}

// 使用示例
const historyCache = new LRUCache(5); // 設置緩存容量為5

historyCache.put("Page 1", "www.page1.com");
historyCache.put("Page 2", "www.page2.com");
historyCache.put("Page 3", "www.page3.com");
historyCache.get("Page 1");

// 輸出瀏覽歷史記錄
historyCache.displayHistory();

在上面的示例中,LRUCache 類實現(xiàn)了一個簡單的 LRU 緩存,通過 get 方法獲取歷史記錄,并通過 put 方法添加歷史記錄。displayHistory 方法用于展示瀏覽歷史記錄。

可以根據實際需求進一步擴展和優(yōu)化這個示例,比如添加時間戳來記錄訪問時間、持久化歷史記錄到本地存儲等功能。希望這個示例能幫助你實現(xiàn)瀏覽歷史記錄功能。

以上就是使用JavaScript實現(xiàn)LRU緩存的代碼詳解的詳細內容,更多關于JavaScript LRU緩存的資料請關注腳本之家其它相關文章!

相關文章

  • .net MVC+Bootstrap下使用localResizeIMG上傳圖片

    .net MVC+Bootstrap下使用localResizeIMG上傳圖片

    這篇文章主要為大家詳細介紹了.net MVC和Bootstrap下使用 localResizeIMG上傳圖片,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • JavaScript練習小項目之修改div塊的顏色

    JavaScript練習小項目之修改div塊的顏色

    這篇文章主要給大家介紹了關于JavaScript練習小項目之修改div塊的顏色的相關資料,文中通過舉例介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2023-01-01
  • JavaScript 亂碼問題

    JavaScript 亂碼問題

    在用js寫網頁時,如果html等內容全部用document.write輸出,包括<html>、<meta等標簽,當嵌套時,會出現(xiàn)輸出內容為亂碼的問題
    2009-08-08
  • js Canvas繪制圓形時鐘效果

    js Canvas繪制圓形時鐘效果

    這篇文章主要為大家詳細介紹了js Canvas繪制圓形時鐘效果的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 多種方式實現(xiàn)js圖片預覽

    多種方式實現(xiàn)js圖片預覽

    這篇文章主要為大家詳細介紹了多種方式實現(xiàn)js圖片預覽,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 收藏一個代碼

    收藏一個代碼

    收藏一個代碼...
    2006-08-08
  • 微信小程序實現(xiàn)性別單選效果

    微信小程序實現(xiàn)性別單選效果

    這篇文章主要為大家詳細介紹了微信小程序實現(xiàn)性別單選效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • JS新標簽頁打開的方法大全(讓你的網站訪問更加便捷)

    JS新標簽頁打開的方法大全(讓你的網站訪問更加便捷)

    在開發(fā)Web應用中我們常常需要在當前頁面打開一個鏈接,但又不希望離開當前頁面,這篇文章主要給大家介紹了關于JS新標簽頁打開的方法大全,通過這些方法可以讓你的網站訪問更加便捷,需要的朋友可以參考下
    2023-10-10
  • JavaScript知識點整理

    JavaScript知識點整理

    本文是腳本之家小編日常整理的關于javascript知識點,包括javascript擁有的特點,組成部分,數(shù)據類型等方面,對javascript知識點相關知識感興趣的朋友一起學習吧
    2015-12-12
  • js獲得當前時區(qū)夏令時發(fā)生和終止的時間代碼

    js獲得當前時區(qū)夏令時發(fā)生和終止的時間代碼

    這篇文章主要介紹了js獲得當前時區(qū)夏令時發(fā)生和終止的時間代碼,需要的朋友可以參考下
    2014-02-02

最新評論