|
|
简介
LinkedHashMap
是HashMap
的子类,也是对Map
接口的一种基于链表和哈希表的实现,不过扩展了HashMap增加了双向链表的实现。
相较于HashMap的迭代器中混乱的访问顺序,LinkedHashMap可以提供可以预测的迭代访问,即按照插入顺序(insertion-order)或访问序(access-order)来对哈希表中的元素进行迭代。
- 插入序(insertion-order):就是Entry被添加到Map中的顺序。
- 访问序(access-order):是对所有Entry按照最近访问(least-recently)到最远访问(most-recently)进行排序,读写都会影响到访问顺序,但是对迭代器(
entrySet()
、keySet()
、values()
)的访问不会影响到访问顺序。访问顺序使得可以通过LinkedHashMap来实现一个LRU(least-recently-used)Cache。
LinkedHashMap 继承自 HashMap,并在其基本结构上增加了双向链表的实现,因而 LinkedHashMap 在内存占用上要比 HashMap 高出许多。
LinkedHashMap 仍然沿用了 HashMap 中基于桶数组、桶内单链表和红黑树结构的哈希表,在哈希计算、定位、扩容等方面都和 HashMAp 是一致的。LinkedHashMap 同样支持为 null 的键和值。
源码分析
属性
|
|
构造方法
LinkedHashMap的构造函数总是在第一行调用父类构造函数,accessOrder默认为false(即默认按照插入顺序访问)。
节点
LinkedHashMap.Entry
继承自HashMap.Node
,而HashMap.TreeNode
又继承了LinkedHashMap.Entry
。
LinkedHashMap只会对双向链表的关系进行管理,单向链表的关系仍由其父类进行管理。
方法
创建节点
重写了父类HashMap的newNode和newTreeNode方法,并将创建的新节点插入到双链表末尾。
链接变化
|
|
节点变化
|
|
维护插入序和访问序
在新建节点的时候,都是将新建节点链接到双向链表的末尾。从双向链表的尾部向头部遍历就可以保证插入顺序了。
在插入节点、删除节点和访问节点后会调用相应的回调函数(在HashMap中是空实现),LinkedHashMap通过实现这些回调函数实现了访问顺序的维护。
遍历
LinkedHashMap的所有节点都在一个双向链表中,因此可以通过双向链表来遍历所有的Entry。
迭代器
|
|
遍历方法
|
|
感谢:
http://blog.jrwang.me/2016/java-collections-linkedhashmap/