今天刷到一道不错的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新特新实现简洁优雅了很多。
Comments | NOTHING