LRU 缓存介绍
我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力会有很大提高。但是,当我们读取的个数特别大的时候,我们不可能把所有已经读取的数据都放在缓存里,毕竟内存大小是一定的,我们一般把最近常读取的放在缓存里
LinkedHashMap解析
要实现 LRU 缓存,我们首先要用到一个类 LinkedHashMap。
用这个类有两大好处:一是它本身已经实现了按照访问顺序的存储,也就是说,最近读取的会放在最前面,最最不常读取的会放在最后(当然,它也可以实现按照插入顺序存储)。第二,LinkedHashMap 本身有一个方法用于判断是否需要移除最不常读取的数,但是,原始方法默认不需要移除(这是,LinkedHashMap 相当于一个linkedlist),所以,我们需要 override 这样一个方法,使得当缓存里存放的数据个数超过规定个数后,就把最不常用的移除掉。关于 LinkedHashMap 中已经有详细的介绍。
/**
* Constructs an empty
<tt>
LinkedHashMap
</tt>
instance with the
* specified initial capacity, load factor and ordering mode.
*
*
@param
initialCapacity
the initial capacity
*
@param
loadFactor
the load factor
*
@param
accessOrder
the ordering mode -
<tt>
true
</tt>
for
* access-order,
<tt>
false
</tt>
for insertion-order
*
@throws
IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public
LinkedHashMap(
int
initialCapacity,
float
loadFactor,
boolean
accessOrder) {
super
(initialCapacity, loadFactor);
this
.
accessOrder
= accessOrder;
}
/**
* Returns
<tt>
true
</tt>
if this map should remove its eldest entry.
* This method is invoked by
<tt>
put
</tt>
and
<tt>
putAll
</tt>
after
* inserting a new entry into the map. It provides the implementor
* with the opportunity to remove the eldest entry each time a new one
* is added. This is useful if the map represents a cache: it allows
* the map to reduce memory consumption by deleting stale entries.
*
*
<p>
Sample use: this override will allow the map to grow up to 100
* entries and then delete the eldest entry each time a new entry is
* added, maintaining a steady state of 100 entries.
*
<pre>
* private static final int MAX_ENTRIES = 100;
*
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() > MAX_ENTRIES;
* }
*
</pre>
*
*
<p>
This method typically does not modify the map in any way,
* instead allowing the map to modify itself as directed by its
* return value. It
<i>
is
</i>
permitted for this method to modify
* the map directly, but if it does so, it
<i>
must
</i>
return
*
<tt>
false
</tt>
(indicating that the map should not attempt any
* further modification). The effects of returning
<tt>
true
</tt>
* after modifying the map from within this method are unspecified.
*
*
<p>
This implementation merely returns
<tt>
false
</tt>
(so that this
* map acts like a normal map - the eldest element is never removed).
*
*
@param
eldest
The least recently inserted entry in the map, or if
* this is an access-ordered map, the least recently accessed
* entry. This is the entry that will be removed it this
* method returns
<tt>
true
</tt>
. If the map was empty prior
* to the
<tt>
put
</tt>
or
<tt>
putAll
</tt>
invocation resulting
* in this invocation, this will be the entry that was just
* inserted; in other words, if the map contains a single
* entry, the eldest entry is also the newest.
*
@return
<tt>
true
</tt>
if the eldest entry should be removed
* from the map;
<tt>
false
</tt>
if it should be retained.
*/
protected boolean
removeEldestEntry(Map.Entry<
K
,
V
> eldest) {
return false
;
}
实战
final int
cacheSize =
10
;
LinkedHashMap<String, String> map =
new
LinkedHashMap<String, String>(
16
,
0.75F
,
true
){
@Override
protected boolean
removeEldestEntry(Map.Entry<String, String> eldest) {
return
size() >
cacheSize
;
}
};
封装工具类
import
java.util.LinkedHashMap;
import
java.util.Map;
/**
* LRU
缓存
*
@param
<K>
*
@param
<V>
*/
public class
LRUCache<
K
,
V
>
extends
LinkedHashMap<
K
,
V
> {
private int
cacheSize
;
public
LRUCache(
int
cacheSize) {
super
(
16
,
0.75F
,
true
);
this
.
cacheSize
= cacheSize;
}
protected boolean
removeEldestEntry(Map.Entry<
K
,
V
> eldest) {
return
size() >=
cacheSize
;
}
}