泛型实现 LRU 缓存
- LRU(Least Recently Used,最近最久未使用)缓存思想:
(1)固定缓存大小,需要给缓存分配一个固定的大小
(2)每次读取缓存都会改变缓存的使用时间,将缓存的存在时间重新刷新
(3)需要在缓存满了后,将最近最久未使用的缓存删除,再添加最新的缓存
- 实现思路:使用LinkedHashMap来实现LRU缓存。
LinkedHashMap的一个构造函数:
public LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder) {super(initialCapacity, loadFactor);this.accessOrder = accessOrder;}
传入的第三个参数:
accessOrder为true的时候,就按访问顺序对LinkedHashMap排序,
accessOrder为false的时候,就按插入顺序(默认情况)。
当把accessOrder设置为true后(按照访问顺序),就可以将最近访问的元素置于最前面。这样就可以满足上述的(2)。
LinkedHashMap是自动扩容的,当table数组中元素大于Capacity loadFactor的时候,就会自动进行两倍扩容。但是为了使缓存大小固定,就需要在初始化的时候传入容量大小和*负载因子。为了使得到达设置缓存大小不会进行自动扩容,需要将初始化的大小进行计算再传入,将初始化大小设置为(缓存大小 / loadFactor) + 1,这样就可以在元素数目达到缓存大小时,也不会进行扩容了。这样就解决了上述的(1)。
实现
```java public class LRUCache{ private final int MAX_CACHE_SIZE; private final float DEFAULT_LOAD_FACTORY = 0.75f; private LinkedHashMap map;; public LRUCache(int cacheSize){
MAX_CACHE_SIZE=cacheSize;int capacity=(int)Math.ceil(MAX_CACHE_SIZE/DEFAULT_LOAD_FACTORY)+1;//初始化大小设置为(缓存大小 / loadFactor) + 1,这样就可以在元素数目达到缓存大小时,也不会进行扩容map=new LinkedHashMap<K,V>(capacity,DEFAULT_LOAD_FACTORY,true){//true表示按照访问顺序@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size()>MAX_CACHE_SIZE;}};
}
//为了线程安全所有方法都是同步方法 public synchronized void put(K key,V value){
map.put(key,value);
}
public synchronized V get(K key){
return map.get(key);
}
public synchronized void remove(K key){
map.remove(key);
}
public synchronized Set
> getAll(){ return map.entrySet();
}
@Override public String toString() {
StringBuilder sb=new StringBuilder();for(Map.Entry<K,V> entry:map.entrySet()){sb.append(String.format("%s: %s\n",entry.getKey(),entry.getValue()));}return sb.toString();
}
public static void main(String[] args) {
LRUCache<Integer,Integer> lru=new LRUCache<Integer, Integer>(5);//该缓存的容量是5lru.put(1, 1);lru.put(2, 2);lru.put(3, 3);System.out.println(lru);lru.get(1); //这里访问了 key=1的元素//按照访问顺序排序 --> key=1的元素是最新才访问的,所以key=2的元素是最近最久未访问的元素System.out.println(lru);lru.put(4,4);lru.put(5,5);lru.put(6,6);//容器的容量是5,当超过该容量时,会删除最近最久未访问的元素,也就是删除了key=2的元素System.out.println(lru);
} } /* 输出结果 1: 1 2: 2 3: 3
2: 2 3: 3 1: 1
3: 3 1: 1 4: 4 5: 5 6: 6 */
<a name="djg6y"></a>### 泛型实现 FIFO 缓存- FIFO设计思路:FIFO就是先进先出,可以使用LinkedHashMap进行实现。<br />LinkedHashMap 的构造函数:```javapublic LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder) {super(initialCapacity, loadFactor);this.accessOrder = accessOrder;}
当第三个参数传入为false或者是默认的时候,就可以实现按插入顺序排序,就可以实现FIFO缓存了。
public class FIFOCache<K,V> {private final int MAX_CACHE_SIZE;private final float DEFAULT_LOAD_FACTORY = 0.75f;private LinkedHashMap<K, V> map;public FIFOCache(int cacheSize) {this.MAX_CACHE_SIZE = cacheSize;int capacity = (int)Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTORY) + 1;map=new LinkedHashMap<K,V>(capacity,DEFAULT_LOAD_FACTORY,false){@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > MAX_CACHE_SIZE;}};}public synchronized void put(K key,V value){map.put(key,value);}public synchronized V get(K key){return map.get(key);}public synchronized void remove(K key){map.remove(key);}public synchronized Set<Map.Entry<K,V>> getAll(){return map.entrySet();}@Overridepublic String toString() {StringBuilder sb=new StringBuilder();for(Map.Entry<K,V> entry:map.entrySet()){sb.append(String.format("%s: %s\n",entry.getKey(),entry.getValue()));}return sb.toString();}public static void main(String[] args) {//按照插入顺序FIFOCache<Integer,Integer> fifo=new FIFOCache<Integer, Integer>(5);fifo.put(1, 1);fifo.put(2, 2);fifo.put(3, 3);System.out.println(fifo);fifo.get(1);System.out.println(fifo);fifo.put(4,4);fifo.put(5,5);fifo.put(6,6);System.out.println(fifo);}}/* 输出结果1: 12: 23: 31: 12: 23: 32: 23: 34: 45: 56: 6*/
