LinkedHashMap实现缓存

来源:互联网 发布:python telnetlib详解 编辑:程序博客网 时间:2024/06/05 14:47

首先我们来看看LinkedHashMap的一些特性。通常我们新建一个LinkedHashMap,是这样创建的 new LinkedHashMap<K,V>();这是LinkedHashMap的默认构造方法,这样新建的LinkedHashMap中 元素的排序方式是put 时进去的顺序以后顺序也不会改变。而LinkedHashMap还提供了另外一种构造方法

new LinkedHashMap<>(initialCapacity, loadFactor, accessOrder) ,三个参数分别为,LinkedHashMap初始容量(记住不是大小而是容量,容量表示有能力容纳多少个元素,而大小是当前map包含的元素个数,当然初始化的时候大小为0)、LinkedHashMap的加载因子一般我们设为 0.75f (加载因子的意思是,当map的大小超过 initialCapacity*loadFactor,map就会扩容)、accessOrder为true表示map会根据访问顺序来调整元素内部顺序。

LinkedHashMap的get()方法除了返回元素之外还可以把被访问的元素放到链表的底端,所以最近访问的元素将会在最下面(链表的底端)。下面给一个例子

public class Test {public static void main(String[] args) {Map<String,String> map = new LinkedHashMap<String,String>(5, 0.75f, true);map.put("a", "1");map.put("b", "2");map.put("c", "3");map.put("d", "4");map.put("e", "5");//输出map的默认顺序for(Map.Entry<String, String> mEntry : map.entrySet()){System.out.println(mEntry.getKey()+","+mEntry.getValue());}map.get("b");map.get("d");System.out.println();//输出map因为访问  导致的顺序改变后的顺序for(Map.Entry<String, String> mEntry : map.entrySet()){System.out.println(mEntry.getKey()+","+mEntry.getValue());}}}
输出结果:

a,1
b,2
c,3
d,4
e,5


a,1
c,3
e,5
b,2
d,4

我们可以看到 最近访问的两个元素跑到了最下面(链表的底端)。

下面来实现一个类继承LinkedHashMap来实现缓存 (注意 linkedHashMap 不是线程安全的,所有其实现的缓存也不是线程安全的)

1 新建一个LRUCache类实现缓存

public class LRUCache<K,V> extends LinkedHashMap<K,V>{private int capacity = 16;//默认最大缓存数为16public LRUCache(){super(16,0.75f,true);}/** * @param capacity 设定缓存数 */public LRUCache(int capacity){super(16,0.75f,true);this.capacity = capacity;}/** * 我们提供的删除缓存策略是: * 当 LinkedHashMap的大小大于 我们设定的容量时 移除链表最顶端元素 */@Overridepublic boolean removeEldestEntry(Map.Entry<K, V> entry){//重写LinkedHashMap 的 removeEldestEntry 方法,控制 removeEldestEntry 的移除//下面的size()方法也是来自于LinkedHashMap,其返回LinkedHashMap当前元素个数return size()>capacity;}}

2 新建一个测试类

public class Test {public static void main(String[] args) {LRUCache<String,String> map = new LRUCache<String,String>(5);map.put("a", "1");map.put("b", "2");map.put("c", "3");map.put("d", "4");map.put("e", "5");//输出map的默认顺序for(Map.Entry<String, String> mEntry : map.entrySet()){System.out.println(mEntry.getKey()+","+mEntry.getValue());}map.get("b");map.get("d");map.put("f", "6");map.put("g", "7");System.out.println();//输出map因为访问  导致的顺序改变后的顺序for(Map.Entry<String, String> mEntry : map.entrySet()){System.out.println(mEntry.getKey()+","+mEntry.getValue());}}}

运行结果:

a,1
b,2
c,3
d,4
e,5


e,5
b,2
d,4
f,6
g,7

从结果中可以看到 访问map的元素 b ,d 后 d ,b 移动到了链表的最底层,然后map put了两个元素,这两个元素就占据了链表的最底层,并且由于我们创建的缓存容量为5 新增两个元素后,超出了缓存容量,因此将链表最顶端的两个元素 a 和 c删除了。





原创粉丝点击