package com.coding.basic.linklist;
import java.util.HashMap;
/**
* 用双向链表实现LRU算法
* @author liuxin
*
*/
public class LRUPageFrame {
public static void main(String[] args){
LRUPageFrame frame = new LRUPageFrame(3);
frame.access(7);
frame.access(0);
frame.access(1);
System.out.println("array: " + frame.toString());
frame.access(2);
System.out.println("array: " + frame.toString());
frame.access(0);
System.out.println("array: " + frame.toString());
frame.access(0);
System.out.println("array: " + frame.toString());
frame.access(3);
System.out.println("array: " + frame.toString());
//frame.printList();
frame.access(0);
//frame.printList();
System.out.println("array: " + frame.toString());
System.out.println();
frame.access(4);
//frame.printList();
System.out.println(frame);
}
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
}
private int capacity;
private int count;
private Node first;// 链表头
private Node last;// 链表尾
private HashMap<Integer, Node> keyHash;
public LRUPageFrame(int capacity) {
this.capacity = capacity;
this.count = 0;
keyHash = new HashMap<Integer, Node>();
first = new Node();
first.pageNum = -99;
last = new Node();
last.pageNum = -99;
first.next = last;
}
/**
* 获取缓存中对象
*
* @param key
* @return
*/
public void access(int pageNum) {
Node targetPageNode = keyHash.get(new Integer(pageNum));
if(targetPageNode == null){
targetPageNode = new Node();
targetPageNode.pageNum = pageNum;
addNewPage(targetPageNode);
}
else{
moveToTop(targetPageNode);
}
}
/*
* null - first - f1 - f2 -f3
*/
private void moveToTop(Node targetNode){
if(targetNode != first.next){
targetNode.prev.next = targetNode.next;
if(targetNode.next != null){
targetNode.next.prev = targetNode.prev;
}
targetNode.next = first.next;
if(first.next != null){
first.next.prev = targetNode;
}
first.next = targetNode;
targetNode.prev = first;
}
}
private void addNewPage(Node targetPageNode){
//first.next ?= null
//
targetPageNode.next = first.next;
if(first.next != null){
first.next.prev = targetPageNode;
}
first.next = targetPageNode;
targetPageNode.prev = first;
keyHash.put(targetPageNode.pageNum, targetPageNode);
count++;
if(count > capacity){
popOutLast();
}
}
/*
* t3 - t2 - t1 - last - null
*/
private void popOutLast(){
Node tailNode = last.prev; //t1
if(tailNode != null){
Node preTailNode = tailNode.prev; //t2
if(preTailNode != null){
keyHash.remove(preTailNode.pageNum);
preTailNode.next = last; //t2 -> last
last.prev = preTailNode;
count --;
}
}
}
public void printList(){
int tmpcount = 0;
Node node = first.next;
while(node != last && tmpcount++<20){
System.out.println("current: "+node.pageNum+ " parent: " + node.prev.pageNum);
node = node.next;
}
}
public String toString(){
StringBuilder buffer = new StringBuilder();
Node node = first.next;
while(node != null){
if(node == last) break;
buffer.append(node.pageNum);
node = node.next;
if(node != null){
buffer.append(",");
}
}
String returnStr = null;
if(buffer.charAt(buffer.length() -1 ) == ','){
returnStr = buffer.substring(0, buffer.length() -1);
}else{
returnStr = buffer.toString();
}
return returnStr;
}
}