Lru cache

LRU cache 其實很好理解,就是邊緣人理論

一個 node 如果被不理很久(write or read),那位子滿了就自然要把這個邊緣人 node 趕出去,

這世界就是這麼現實QQ

Requirement

READ O(1)

WRITE O(1)

Map

Linked List

reduce time, increase capcity

Implement LRU Cache

class LRUCacheNode {
  key: string;
  value: any;
  next: LRUCacheNode | null;
  prev: LRUCacheNode | null;

  constructor(
    key: string,
    value: string,
    next: LRUCacheNode | null = null,
    prev: LRUCacheNode | null = null
  ) {
    this.key = key;
    this.value = value;
    this.next = next;
    this.prev = prev;
  }
}
export class LRUCache {
  size: number;
  limit: number;
  head: LRUCacheNode | null;
  tail: LRUCacheNode | null;
  cacheMap: Record<string, LRUCacheNode>;

  constructor(limit = 10) {
    this.size = 0;
    this.limit = limit;
    this.head = null;
    this.tail = null;
    this.cacheMap = {};
  }

  private detach(node: LRUCacheNode) {
    if (node.prev instanceof LRUCacheNode) {
      node.prev.next = node.next;
    } else {
      this.head = node.next;
    }

    if (node.next instanceof LRUCacheNode) {
      node.next.prev = node.prev;
    } else {
      this.tail = node.prev;
    }
  }

  public write(key: string, value: string) {
    const existingNode = this.cacheMap[key];

    if (existingNode) {
      this.detach(existingNode);
      this.size--;
    } else if (this.size === this.limit && this.tail) {
      delete this.cacheMap[this.tail.key];
      this.detach(this.tail);
      this.size--;
    }

    if (!this.head) {
      this.head = this.tail = new LRUCacheNode(key, value);
    } else {
      const node = new LRUCacheNode(key, value, this.head);
      this.head.prev = node;
      this.head = node;
    }

    this.cacheMap[key] = this.head;
    this.size++;
  }

  public read(key: string) {
    const existingNode = this.cacheMap[key];

    if (existingNode) {
      const value = existingNode.value;

      if (this.head !== existingNode) {
        this.write(key, value);
      }

      return value;
    } else {
      console.log(`Item not vailable in cache for key ${key}`);
    }
  }

  public clear() {
    this.head = null;
    this.tail = null;
    this.size = 0;
    this.cacheMap = {};
  }
}

If consecutive cache his(2 or more time) are count as being used

export class LRUCache {
  size: number;
  limit: number;
  head: LRUCacheNode | null;
  tail: LRUCacheNode | null;
  cacheMap: Record<string, LRUCacheNode>;

  constructor(limit = 10) {
    this.size = 0;
    this.limit = limit;
    this.head = null;
    this.tail = null;
    this.cacheMap = {};
  }

  private detach(node: LRUCacheNode) {
    if (node.prev instanceof LRUCacheNode) {
      node.prev.next = node.next;
    } else {
      this.head = node.next;
    }

    if (node.next instanceof LRUCacheNode) {
      node.next.prev = node.prev;
    } else {
      this.tail = node.prev;
    }
  }

  public write(key: string, value: string) {
    const existingNode = this.cacheMap[key];
    
    /** If the hit is less than twice, the linked-list will not be changed */
    if (existingNode && existingNode.hits < 1) {
      existingNode.value = value;
      existingNode.hits++;
      return;
    }

    if (existingNode) {
      this.detach(existingNode);
      this.size--;
    } else if (this.size === this.limit && this.tail) {
      delete this.cacheMap[this.tail.key];
      this.detach(this.tail);
      this.size--;
    }

    if (!this.head) {
      this.head = this.tail = new LRUCacheNode(key, value);
    } else {
      const node = new LRUCacheNode(key, value, this.head);
      this.head.prev = node;
      this.head = node;
    }

    this.cacheMap[key] = this.head;
    this.size++;
  }

  public read(key: string) {
    const existingNode = this.cacheMap[key];

    if (existingNode) {
      const value = existingNode.value;

      if (this.head !== existingNode) {
        this.write(key, value);
      }

      return value;
    } else {
      console.log(`Item not vailable in cache for key ${key}`);
    }
  }

  public clear() {
    this.head = null;
    this.tail = null;
    this.size = 0;
    this.cacheMap = {};
  }
}

LRU Cache

By Jay Chou

LRU Cache

  • 167