package me.lzb.basic;
/**
* 用双向链表实现LRU算法
* @author lzb
*
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node(Node prev, Node next, int pageNum) {
this.prev = prev;
this.next = next;
this.pageNum = pageNum;
}
}
private int capacity;
private Node first;// 链表头
private Node last;// 链表尾
public LRUPageFrame(int capacity) {
if(capacity < 1){
// throw new Exception("capacity boom");
}
this.capacity = capacity;
}
/**
* 获取缓存中对象
*
* @param pageNum
* @return
*/
public void access(int pageNum) {
if(capacity == 1){
first = last = new Node(null, null, pageNum);
return;
}
if(first == null){
first = last = new Node(null, null, pageNum);
return;
}
if(first.pageNum == pageNum){
return;
}
Node tmp = first;
int size = 0;
for (int i = 0; i < capacity; i++) {
size = size + 1;
//如果发现一样的,把这个挪到最前面
if(tmp.pageNum == pageNum){
moveToFirst(tmp);
return;
}
//链表已经循环结束,但是个数还没满,更新last
if(tmp.next == null){
last = tmp;
break;
}
tmp = tmp.next;
}
//没有相同的,在最顶端插入
Node f = new Node(null, first, pageNum);
addAsFirst(f);
//已经放满,更新last
if(size >= capacity){
removeLastOne();
}
}
/**
* 删除最后一个节点
*/
private void removeLastOne(){
last = last.prev;
//使GC ROOT 不可达
last.next.prev = null;
last.next = null;
}
/**
* 把某节点移动到最顶部
* @param tmp 在链表中的任意节点
*/
private void moveToFirst(Node tmp){
if(tmp == first){
return;
}
if (tmp.next != null){
tmp.next.prev = tmp.prev;
tmp.prev.next = tmp.next;
}else {
tmp.prev.next = null;
//当这个节点是last的时候,更新last
last = tmp.prev;
}
tmp.next = first;
tmp.prev = null;
first.prev = tmp;
first = tmp;
}
/**
* 在顶部增加一个节点
* @param node node
*/
private void addAsFirst(Node node){
first.prev = node;
first = node;
}
/**
* ASC
* @return
*/
public String toString(){
StringBuilder buffer = new StringBuilder();
Node node = first;
while(node != null){
buffer.append(node.pageNum);
node = node.next;
if(node != null){
buffer.append(",");
}
}
return buffer.toString();
}
/**
* DESC
* @return
*/
public String toStringDESC(){
StringBuilder buffer = new StringBuilder();
Node node = last;
while(node != null){
buffer.append(node.pageNum);
node = node.prev;
if(node != null){
buffer.append(",");
}
}
return buffer.toString();
}
}