参考文章
- LinkedHashMap 源码详细分析(JDK1.8)
继承关系
LinkedHashMap 继承自 HashMap,其大部分方法都是直接使用或稍微修改 Hash Map 的方法,不同点在于它还维护了一个双向链表结构
数据结构
底层由桶数组+链表或红黑树组成,并在此基础上维护了双向链表保证遍历的顺序性
如何实现维护双向链表?
- 按照插入顺序维护双向链表
当 accessOrder = false 时(默认),按照插入顺序维护双向链表。LinkedHashMap 没有直接重写 put 或 putVal,remove 或 removeNode 方法,而是:
- 在插入时:重写了
newNode(...)方法,将节点替换为内部类LinkedHashMap.Entry ,然后通过新增的linkNodeLast(...)方法将插入的节点连接起来; - 在删除时:重写了
afterNodeRemoval(...)方法,HashMap 在实现时已经考虑到 LinkedHashMap 删除节点,因此在removeNode(...)调用了此方法,只不过在 HashMap 中此方法的实现是空的
- 在上面的基础上,按照访问顺序维护双向链表
当 accessOrder = true 时,按照访问顺序维护维护双向链表,访问完指定的 key 之后会调用 afterNodeAccess(...)把此节点移动到链表尾部
HashMap 为 LinkedHashMap 预留了哪些回调函数
// Callbacks to allow LinkedHashMap post-actionsvoid afterNodeAccess(Node<K,V> p) { }void afterNodeInsertion(boolean evict) { }void afterNodeRemoval(Node<K,V> p) { }
1和3在上面已经介绍了用处了,2需要配合 removeEldestEntry(...)一起用,不过在 LinkedHashMap 中是不起作用的,需要子类继承后重写 removeEldestEntry(...)方法,并以实现不同策略的淘汰方法(e.g. 实现缓存的淘汰)
