1. 基于LinkedHashMap
2. 基于HashMap 和 双向链表
import java.util.LinkedHashMap; /** * Created by itworker365 on 5/11/2017. * 基于LinkedHashMap特性,用继承或代理方式,选择基于访问顺序并在继承后重写removeEldestEntry当超过容量时返回true。
* 基本测试看代码知道这个结构的实现就很清楚了,不用写了。 */ public class LRUCacheUseLinkedHashmap { public static void main(String[] args) { /** * LinkedHashMap 参数说明 * initialCapacity the initial capacity * loadFactor the load factor * accessOrder the ordering mode - <tt>true</tt> for access-order, <tt>false</tt> for insertion-order */ LinkedHashMap<Integer, Integer> linkedHashMapInsertionOrder = new LinkedHashMap<>(5, 10, false); linkedHashMapInsertionOrder.put(1, 111); linkedHashMapInsertionOrder.put(3, 333); linkedHashMapInsertionOrder.put(2, 222); System.out.println("linkedHashMapInsertionOrder before get: " + linkedHashMapInsertionOrder.toString()); linkedHashMapInsertionOrder.get(3); System.out.println("linkedHashMapInsertionOrder after get: " + linkedHashMapInsertionOrder.toString()); LinkedHashMap<Integer, Integer> linkedHashMapAccessOrder = new LinkedHashMap<>(5, 10, true); linkedHashMapAccessOrder.put(1, 111); linkedHashMapAccessOrder.put(3, 333); linkedHashMapAccessOrder.put(2, 222); System.out.println("linkedHashMapAccessOrder before get: " + linkedHashMapAccessOrder.toString()); linkedHashMapAccessOrder.get(1); System.out.println("linkedHashMapAccessOrder after get: " + linkedHashMapAccessOrder.toString()); linkedHashMapAccessOrder.put(4, 444); System.out.println("linkedHashMapAccessOrder put: " + linkedHashMapAccessOrder.toString()); } }
import java.util.HashMap; /** * Created by itworker365 on 5/11/2017. */ public class LRUCache { int capacity; HashMap<Integer, Entry> table = new HashMap<Integer, Entry>(); Entry head = null; Entry tail = null; public LRUCache(int capacity) { this.capacity = capacity; } public int get(int key) { if (table.containsKey(key)) { Entry entry = table.get(key); //调整节点位置 NodeChangeAfterAccess(entry); return entry.value; } else { return -1; } } public void set(int key, int value) { if(table.containsKey(key)){ //已经存在节点,则取出更新其value Entry old = table.get(key); old.value = value; //调整节点位置 NodeChangeAfterAccess(old); }else{ Entry created = new Entry(key, value, null, null); //LRU删除队尾元素 if(table.size() >= capacity){ table.remove(tail.key); removeNodeFromList(tail); MoveNodeToHead(created); }else{ MoveNodeToHead(created); } table.put(key, created); } } private void NodeChangeAfterAccess(Entry old) { removeNodeFromList(old); MoveNodeToHead(old); } private void MoveNodeToHead(Entry entry) { //移动节点到头节点 entry.next = head; entry.pre = null; if(head!=null) { head.pre = entry; } head = entry; if(tail ==null) { tail = head; } } private void removeNodeFromList(Entry entry) { //获取后需要调整链表关系除当前位置 if (entry.pre != null) { entry.pre.next = entry.next; } else { head = entry.next; } if (entry.next != null) { entry.next.pre = entry.pre; } else { tail = entry.pre; } } } class Entry { int key; int value; Entry pre; Entry next; public Entry(int key, int value, Entry pre, Entry next) { this.key = key; this.value = value; this.pre = pre; this.next = next; } }