# LRU算法 java实现

Java代码
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Map;

/**
*
*
* @param
* @param
*/
private final int maxCapacity;

private static final float DEFAULT_LOAD_FACTOR = 0.75f;

private final Lock lock = new ReentrantLock();

this.maxCapacity = maxCapacity;
}

@Override
protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
return size() > maxCapacity;
}
@Override
public boolean containsKey(Object key) {
try {
lock.lock();
return super.containsKey(key);
} finally {
lock.unlock();
}
}

@Override
public V get(Object key) {
try {
lock.lock();
return super.get(key);
} finally {
lock.unlock();
}
}

@Override
public V put(K key, V value) {
try {
lock.lock();
return super.put(key, value);
} finally {
lock.unlock();
}
}

public int size() {
try {
lock.lock();
return super.size();
} finally {
lock.unlock();
}
}

public void clear() {
try {
lock.lock();
super.clear();
} finally {
lock.unlock();
}
}

public Collection> getAll() {
try {
lock.lock();
return new ArrayList>(super.entrySet());
} finally {
lock.unlock();
}
}
}

LRU算法还可以通过计数来实现，缓存存储的位置附带一个计数器，当命中时将计数器加1，替换时就查找计数最小的位置并替换，结合访问时间戳来实现。这种算法比较适合缓存数据量较小的场景，显然，遍历查找计数最小位置的时间复杂度为O(n)。我实现了一个，结合了访问时间戳，当最小计数大于MINI_ACESS时(这个参数的调整对命中率有较大影响），就移除最久没有被访问的项：
Java代码
package net.rubyeye.codelib.util.concurrency.cache;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
*类说明：当缓存数目不多时，才用缓存计数的传统LRU算法
* @param
* @param
*/
public class LRUCache implements Serializable {

private static final int DEFAULT_CAPACITY = 100;

protected Map map;

private final Lock writeLock = lock.writeLock();

private final volatile int maxCapacity;  //保持可见性

public static int MINI_ACCESS = 5;

public LRUCache() {
this(DEFAULT_CAPACITY);
}

public LRUCache(int capacity) {
if (capacity <= 0)
throw new RuntimeException("缓存容量不得小于0");
this.maxCapacity = capacity;
this.map = new HashMap(maxCapacity);
}

public boolean ContainsKey(K key) {
try {
return this.map.containsKey(key);
} finally {
}
}

public V put(K key, V value) {
try {
writeLock.lock();
if ((map.size() > maxCapacity - 1) && !map.containsKey(key)) {
// System.out.println("开始");
Set> entries = this.map.entrySet();
removeRencentlyLeastAccess(entries);
}
ValueEntry new_value = new ValueEntry(value);
ValueEntry old_value = map.put(key, new_value);
if (old_value != null) {
new_value.count = old_value.count;
return old_value.value;
} else
return null;
} finally {
writeLock.unlock();
}
}

/**
* 移除最近最少访问
*/
protected void removeRencentlyLeastAccess(
Set> entries) {
// 最小使用次数
long least = 0;
// 访问时间最早
long earliest = 0;
K toBeRemovedByCount = null;
K toBeRemovedByTime = null;
Iterator> it = entries.iterator();
if (it.hasNext()) {
Map.Entry valueEntry = it.next();
least = valueEntry.getValue().count.get();
toBeRemovedByCount = valueEntry.getKey();
earliest = valueEntry.getValue().lastAccess.get();
toBeRemovedByTime = valueEntry.getKey();
}
while (it.hasNext()) {
Map.Entry valueEntry = it.next();
if (valueEntry.getValue().count.get() < least) {
least = valueEntry.getValue().count.get();
toBeRemovedByCount = valueEntry.getKey();
}
if (valueEntry.getValue().lastAccess.get() < earliest) {
earliest = valueEntry.getValue().count.get();
toBeRemovedByTime = valueEntry.getKey();
}
}
// System.out.println("remove:" + toBeRemoved);
// 如果最少使用次数大于MINI_ACCESS，那么移除访问时间最早的项(也就是最久没有被访问的项）
if (least > MINI_ACCESS) {
map.remove(toBeRemovedByTime);
} else {
map.remove(toBeRemovedByCount);
}
}

public V get(K key) {
try {
V value = null;
ValueEntry valueEntry = map.get(key);
if (valueEntry != null) {
// 更新访问时间戳
valueEntry.updateLastAccess();
// 更新访问次数
valueEntry.count.incrementAndGet();
value = valueEntry.value;
}
return value;
} finally {
}
}

public void clear() {
try {
writeLock.lock();
map.clear();
} finally {
writeLock.unlock();
}
}

public int size() {
try {
return map.size();
} finally {
}
}

public long getCount(K key) {
try {
ValueEntry valueEntry = map.get(key);
if (valueEntry != null) {
return valueEntry.count.get();
}
return 0;
} finally {
}
}

public Collection> getAll() {
try {
Set keys = map.keySet();
Map tmp = new HashMap();
for (K key : keys) {
tmp.put(key, map.get(key).value);
}
return new ArrayList>(tmp.entrySet());
} finally {
}
}

class ValueEntry implements Serializable {
private V value;

private AtomicLong count;

private AtomicLong lastAccess;

public ValueEntry(V value) {
this.value = value;
this.count = new AtomicLong(0);
lastAccess = new AtomicLong(System.nanoTime());
}

public void updateLastAccess() {
this.lastAccess.set(System.nanoTime());
}

}
• 本文已收录于以下专栏：

举报原因： 您举报文章：LRU算法 java实现 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)