原题如下:
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
思路:用一个数据结构来实现LRU,对LRU的解释为:Replace the page that has not been used for the longest period of time,即最长时间未被访问的页面,访问包括set和get。
很容易想到用TreeMap来实现,但是实现过程还是有点曲折,TreeMap是有序的Map,是根据key排序的,TreeMap和HashMap根据hashCode()方法和equals()方法来比较key值是否相等,但TreeMap是根据key元素的compareTo方法来排序,在这里因为我们关心的是时间,所以我们希望元素安装时间排序,同时TreeMap结构的key中包含题目中的key值,所以需要一种新的数据结构KeyTime,KeyTime包括key和访问时间,让TreeMap安装访问时间排序,所以需要重写compareTo方法。
完整代码如下:
keyTime用于保存key和访问时间。caches用来保存KeyTime和对应的值。注意每次访问都要修改时间。
import java.util.HashMap; import java.util.Map; import java.util.TreeMap; //Replace the page that has not been used for the longest period of time public class LRUCache { private int size; long timeCounter = 0; //模拟时间点 private HashMap<Integer,Long> keyTime = new HashMap<Integer,Long>(); //不需要有序,这个地方改成TreeMap会变慢(要维持顺序) private TreeMap<KeyTime,Integer> caches = new TreeMap<KeyTime,Integer>(); //有序 public LRUCache(int capacity) { this.size = capacity; } public int get(int key) { if(keyTime.containsKey(key)){ long newTime = timeCounter++; KeyTime kt = new KeyTime(key,keyTime.get(key).longValue()); int value = caches.get(kt); keyTime.put(key, newTime); caches.remove(kt); caches.put(new KeyTime(key,newTime), value); return value; } return -1; } public void set(int key, int value) { long newTime = timeCounter++; if(keyTime.containsKey(key)){ //已经存在 long oldTime = keyTime.get(key); keyTime.put(key, newTime); caches.remove(new KeyTime(key,oldTime)); caches.put(new KeyTime(key,newTime), value); }else if(keyTime.size()<this.size){ //不存在但未满 keyTime.put(key, newTime); caches.put(new KeyTime(key,newTime), value); }else{ //不存在,而且满了 Map.Entry<KeyTime,Integer> firstEntry = caches.firstEntry(); int k = firstEntry.getKey().key; long time = firstEntry.getKey().time; caches.remove(new KeyTime(k,time)); keyTime.remove(k); keyTime.put(key, newTime); caches.put(new KeyTime(key,newTime), value); } } class KeyTime implements Comparable<KeyTime>{ int key; long time; public KeyTime(int key,long time){ this.key = key; this.time = time; } @Override public int compareTo(KeyTime o) { //重写compareTo方法 if(this.time<o.time){ return -1; }else if(this.time>o.time){ return 1; } return 0; } } }