在理解了#7 介绍的HashMap后,咱们来学习LinkedHashMap的工做原理及实现。首先仍是相似的,咱们写一个简单的LinkedHashMap的程序:html
1node 2git 3github 4app 5函数 6post 7学习 8spa 93d 10 11 12 |
|
运行结果是:
1 2 3 4 5 6 7 8 |
|
咱们能够观察到,和HashMap的运行结果不一样,LinkedHashMap的迭代输出的结果保持了插入顺序。是什么样的结构使得LinkedHashMap具备如此特性呢?咱们仍是同样的看看LinkedHashMap的内部结构,对它有一个感性的认识:
没错,正如官方文档所说:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked listrunning through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
LinkedHashMap是Hash表和链表的实现,而且依靠着双向链表保证了迭代顺序是插入的顺序。
在HashMap中提到了下面的定义:
1 2 3 4 |
|
LinkedHashMap继承于HashMap,所以也从新实现了这3个函数,顾名思义这三个函数的做用分别是:节点访问后、节点插入后、节点移除后作一些事情。
afterNodeAccess函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
就是说在进行put以后就算是对节点的访问了,那么这个时候就会更新链表,把最近访问的放到最后,保证链表。
afterNodeInsertion函数
1 2 3 4 5 6 7 8 |
|
若是用户定义了removeEldestEntry
的规则,那么即可以执行相应的移除操做。
afterNodeRemoval函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
这个函数是在移除节点后调用的,就是将节点从双向链表中删除。
咱们从上面3个函数看出来,基本上都是为了保证双向链表中的节点次序或者双向链表容量所作的一些额外的事情,目的就是保持双向链表中节点的顺序要从eldest到youngest。
put
函数在LinkedHashMap中未从新实现,只是实现了afterNodeAccess
和afterNodeInsertion
两个回调函数。get
函数则从新实现并加入了afterNodeAccess
来保证访问顺序,下面是get
函数的具体实现:
1 2 3 4 5 6 7 8 |
|
值得注意的是,在accessOrder模式下,只要执行get或者put等操做的时候,就会产生structural modification
。官方文档是这么描述的:
A structural modification is any operation that adds or deletes one or more mappings or, in the case of access-ordered linked hash maps, affects iteration order. In insertion-ordered linked hash maps, merely changing the value associated with a key that is already contained in the map is not a structural modification. In access-ordered linked hash maps, merely querying the map with get is a structural modification.
不要犯了像ConcurrentModificationException with LinkedHashMap相似的问题。
总之,LinkedHashMap不愧是HashMap的儿子,和老子太像了,固然,青出于蓝而胜于蓝,LinkedHashMap的其余的操做也基本上都是为了维护好那个具备访问顺序的双向链表