转自:《程序员》 文/ 洪伟铭
cache的所有位置都用双向链表链接起来,当一个位置被命中后,就将通过调整链表的指向将该位置调整到链表的头位置,新加入的内容直接放在链表的头上。这样,在进行过多次查找操作后,最近被命中过的内容就向链表的头移动,而没有被命中的内容就向链表的后面移动。当需要替换时,链表最后的位置就是最近最少被命中的位置,我们只需要将新的内容放在链表前面,淘汰链表最后的位置就是想了LRU算法。
LRU算法的实现
对象设计
对于Cache的每个位置,我们设计一个对象来储存对象的内容,并实现一个双向链表。
其中属性next和prev时双向链表的两个指针,key用于存储对象的键值,value用户存储要cache的对象本身。
我们使用hash算法来从cache中查找对象。
我们使用一个hashmap作为cache,用hashmap的检索机制来实现cache查找;并用head和last两个属性来记录链表的头和尾。并提供put(),getEntry()方法来操作该cache。
算法实现
cache的put()方法可将要缓存的内容放到cache中,在该方法中,对象调用私有方法insert(),将内容放到双向链表的头位置,如果cache满了,则将链表最后的位置淘汰掉:
cache的getEntry()方法可根据输入的内容键值key来查找内容是否存在于cache中,如果命中,这个内容就是最新被使用过的,就需要放到双向链表的头位置。
结束语
LRU算法是cache最常用的算法之一,基于双向链表的实现方式比较容易,并可满足大容量cache的需求,在对系统性能要求越来越高的今天,良好的cache算法有着非常广泛的用途和实现意义。
cache的所有位置都用双向链表链接起来,当一个位置被命中后,就将通过调整链表的指向将该位置调整到链表的头位置,新加入的内容直接放在链表的头上。这样,在进行过多次查找操作后,最近被命中过的内容就向链表的头移动,而没有被命中的内容就向链表的后面移动。当需要替换时,链表最后的位置就是最近最少被命中的位置,我们只需要将新的内容放在链表前面,淘汰链表最后的位置就是想了LRU算法。
LRU算法的实现
对象设计
对于Cache的每个位置,我们设计一个对象来储存对象的内容,并实现一个双向链表。
其中属性next和prev时双向链表的两个指针,key用于存储对象的键值,value用户存储要cache的对象本身。
我们使用hash算法来从cache中查找对象。
我们使用一个hashmap作为cache,用hashmap的检索机制来实现cache查找;并用head和last两个属性来记录链表的头和尾。并提供put(),getEntry()方法来操作该cache。
算法实现
cache的put()方法可将要缓存的内容放到cache中,在该方法中,对象调用私有方法insert(),将内容放到双向链表的头位置,如果cache满了,则将链表最后的位置淘汰掉:
pubilc boolean put(Object key,Object value){
boolean res = false;
HashLinkEntry en = new HashLinkEntry(key , value);
if(map.isEmpty()) {
this.head = en;
this.last = en;
map.put(en.key,en);
res = true;
} else {
HashLinkEntry point = this.getEntry(key);
if(point = null) {
point.value = value;
} else {
this.insert(en);
res = true;
}
}
return res;
}
private void insert(HashLinkEntry en) {
if(map.size() >= this.maxsize) {
HashLinkEntry lastprev = last.prev;
if(lastprev != null) {
map.remove(last.key);
lastprev.next = null;
last = null;
last = lastprev;
} else {
log.error("hashlist get a null point\n" + this.toString());
}
}
map.put(en.key,en );
ent.next = head;
head.prev = en;
head = en;
}
cache的getEntry()方法可根据输入的内容键值key来查找内容是否存在于cache中,如果命中,这个内容就是最新被使用过的,就需要放到双向链表的头位置。
结束语
LRU算法是cache最常用的算法之一,基于双向链表的实现方式比较容易,并可满足大容量cache的需求,在对系统性能要求越来越高的今天,良好的cache算法有着非常广泛的用途和实现意义。