建议先看HahsMap的源码:
https://blog.csdn.net/superprintf/article/details/123874360
LinkedHashMap使用HashMap的模板方法设计模式。HashMap我们清楚,那LinkedList就是按照插入结点的顺序维护一个双向链表。最终达到可以循环访问的效果
一些变量
head是最老的,tail是最年轻的
accessOrder 对访问命令为真,插入命令为false
get方法
调用HashMap中的getNode查找结点。accessOrder为True时,也就是访问模式,执行afterNodeAccess,把访问的元素插入到队尾
可上面modeCount是有关并发控制的东西。
这个afterNodeAccess是LinkedHashMap重写HashMap接口,HashMap中经常使用这个方法。
HashMap中的接口
getOrDefault就很好理解了
modCount
经常能看到这个东西,并发执行的时候会同时修改modeCount导致数量和原先的值对不上,所以会抛出异常ConcurrentModificationException
int mc = modCount;
//执行操作
.......
if (modCount != mc)
throw new ConcurrentModificationException();
newNode
新建结点的时候会插入到队尾
但是要注意LinkedHashMap是重写了HashMap中的newNode方法
在调用hasmap中put方法的时候会使用自己重写的newNode方法
removeEldestEntry
在插入Node结点之后会判断是否需要移除最久未使用结点,通过removeEldestEntry方法
protected方法,可自定义从而实现LRU
afterNodeInsertion方法,也是重写了HashMap中的接口
HashMap中比如说put方法,他最后就会调用这个方法
总结下
LinkedHashMap是在HashMap的基础上维护一个双向链表,是通过重写HashMap中提供的接口注入到HashMap中的方法
比如重写newNode方法,实现了队尾插入逻辑
比如重写afterNodeRemoval方法,实现了修改双向指针的逻辑
而LinkedHashMap自身实现的比较重要的逻辑是removeEldestEntry,我们可以通过实现自己的逻辑来删除最久未使用元素,比如当当前的size大于总的capacity的时候就进行队尾删除。
this.cache = new LinkedHashMap<Integer,Integer>(capacity, 0.75f, true){
@Override
protected boolean removeEldestEntry(Map.Entry eldest){
return cache.size() > capacity;
}
}