|
|
package jmvc.cache;

 /** *//**
*
* @param <K> the type of keys maintained by this cache
* @param <V> the type of cache values
*
* @author Weng Mingjun
* @version 1.00, 07/28/08
*/
public class Cache<K, V>
  {
private int m_size = 0;
private int m_capacity = 0;
private long m_duration = 0;
private Node m_head = new Node();
private Node m_tail = new Node();
private java.util.HashMap<K, Node> m_map = new java.util.HashMap<K, Node>();
 /** *//**
* @param capacity cache items max count
* @param duration cache overdue time span , -1 indicate infinite
*/
public Cache(int capacity, int duration)
 {
this.m_capacity = capacity;
this.m_duration = duration * 1000;
this.m_head.next = this.m_tail;
this.m_tail.prev = this.m_head;
}

//remove the node from the linked list
private void breakLink(Node node)
 {
node.prev.next = node.next;
node.next.prev = node.prev;
}

//set the node as the first node of the linked list
private void asFirstNode(Node node)
 {
node.next = this.m_head.next;
node.prev = this.m_head;
node.next.prev = node;
node.prev.next = node;
}

//set the node as the last node of the linked list
private void asLastNode(Node node)
 {
node.prev = this.m_tail.prev;
node.next = this.m_tail;
node.prev.next = node;
node.next.prev = node;
}

public void set(K k, V v)
 {
Node node = this.m_map.get(k);
//node has exists
if (node != null)
 {
node.load(v);
if (node == this.m_head.next)
return;
breakLink(node);
}
else
 {
//hashtable capacity is sufficent,and create new node add to link
if (this.m_size < this.m_capacity)
 {
node = new Node(k, v);
this.m_map.put(k, node);
this.m_size++;
}
else
 {
//hashtable capacity is overflow , and use the tail
node = this.m_tail.prev;
this.m_map.remove(node.key);
node.load(k, v);
this.m_map.put(k, node);
breakLink(node);
}
}
asFirstNode(node);
}

public V get(K k)
 {
Node node = this.m_map.get(k);
if (node == null)
return null;

//no duration set
if (this.m_duration == -1000 || node.time > System.currentTimeMillis() - this.m_duration)
return node.value;
else
 {
asLastNode(node);
return null;
}
}

//inner class
class Node
 {
public Node()
 {
}

public Node(K k, V v)
 {
this.key = k;
this.value = v;
this.time = System.currentTimeMillis();
}

public void load(K k, V v)
 {
this.key = k;
this.value = v;
this.time = System.currentTimeMillis();
}

public void load(V v)
 {
this.value = v;
this.time = System.currentTimeMillis();
}
public Node prev;
public Node next;
public K key;
public V value;
public long time;
}
} |