Leetcode – 2622. Cache With Time Limit: 有时间限制的缓存


今天刷到一道不错的leetcode题,之所以觉得不错,是一道很好的面向对象的题,所以做个记录。

题目如下:

编写一个类,它允许获取和设置键 - 值对,并且每个键都有一个 过期时间 。

该类有三个公共方法:

set(key, value, duration) :接收参数为整型键 key 、整型值 value 和以毫秒为单位的持续时间 duration 。一旦 duration 到期后,这个键就无法访问。如果相同的未过期键已经存在,该方法将返回 true ,否则返回 false 。如果该键已经存在,则它的值和持续时间都应该被覆盖。

get(key) :如果存在一个未过期的键,它应该返回这个键相关的值。否则返回 - 1 。

count() :返回未过期键的总数。

给出的起始代码是ES5 构造方法 + 原型对象的方式,所以先用这种写法实现了一版本:

var TimeLimitedCache = function () {
  this.map = {};
};

/** 
 * @param {number} key
 * @param {number} value
 * @param {number} duration time until expiration in ms
 * @return {boolean} if un-expired key already existed
 */
TimeLimitedCache.prototype.set = function (key, value, duration) {
  const curr = this.map[key];
  if (this.map[key] !== undefined && (Date.now() - curr?.createTime < duration)) {
    this.map[key] = { value, duration, createTime: Date.now() };
    return true;
  } else {
    this.map[key] = { value, duration, createTime: Date.now() };
    return false;
  }
};

/** 
 * @param {number} key
 * @return {number} value associated with key
 */
TimeLimitedCache.prototype.get = function (key) {
  const curr = this.map[key];
  if (curr !== undefined && (Date.now() - curr?.createTime < curr?.duration)) {
    return curr.value;
  } else {
    return -1;
  }
};

/** 
 * @return {number} count of non-expired keys
 */
TimeLimitedCache.prototype.count = function () {
  let count = 0
  Object.entries(this.map).forEach(([_, item]) => {
    const { duration, createTime } = item;
    if (Date.now() - createTime < duration) {
      count++;
    }
  });
  return count;
};

不过上面的实现还是不够好:
1. ES6+出来好久了,既然题目是要实现一个类,可以用优雅的类语法来实现;
2. 用ES6+中的Map数据类型作为映射数据类型更加专业;
3. 对于已过期的 键-值 直接清除,减少一些每次计算是否过期的逻辑

用ES6+新特性实现一版:

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

  set(key, value, duration) {
    const curr = this.cache.get(key);
    if (curr) {
      clearTimeout(curr.timerId);
    }
    const timerId = setTimeout(() => this.cache.delete(key), duration);
    this.cache.set(key, { value, timerId })
    return !!curr;
  }

  get(key) {
    return this.cache.get(key)?.value ?? -1;
  }

  count() {
    return this.cache.size;
  }
}

可见用ES6新特新实现简洁优雅了很多。


一片冰心在玉壶