[TOC]
引言
Java的集合框架,TreeSet & TreeMap源码解析等…
总体介绍
概括的说,LinkedHashMap
继承自HashMap
,实现了Map<K,V>
接口。其内部还维护了一个双向链表,在每次插入数据,或者访问、修改数据时,会增加节点、或调整链表的节点顺序。以决定迭代时输出的顺序。
默认情况,遍历时的顺序是按照插入节点的顺序。这也是其与HashMap
最大的区别。
也可以在构造时传入accessOrder
参数,使得其遍历顺序按照访问的顺序输出。
节点
LinkedHashMap
的节点Entry<K,V>
继承自HashMap.Node<K,V>
,在其基础上扩展了一下。改成了一个双向链表。
1 | static class Entry<K,V> extends HashMap.Node<K,V> { |
同时类里有两个成员变量head tail
,分别指向内部双向链表的表头、表尾。
1 | //双向链表的头结点 |
方法
LinkedHashMap 最重要的是以下用于维护顺序的函数,它们会在 put、get 等方法中调用。
1 | void afterNodeAccess(Node<K,V> p) { } |
afterNodeAccess()
当一个节点被访问时,如果 accessOrder 为 true,则会将该节点移到链表尾部。也就是说指定为 LRU 顺序之后,在
每次访问一个节点时,会将这个节点移到链表尾部,保证链表尾部是最近访问的节点,那么链表首部就是最近最久未
使用的节点。
1 | void afterNodeAccess(Node<K,V> e) { // move node to last |
afterNodeInsertion()
在 put 等操作之后执行,当 removeEldestEntry() 方法返回 true 时会移除最晚的节点,也就是链表首部节点 first。
evict 只有在构建 Map 的时候才为 false,在这里为 true。
LRU
1 | class test { |
LinkedHashSet
前面已经说过LinkedHashSet是对LinkedHashMap的简单包装,对LinkedHashSet的函数调用都会转换成合适的LinkedHashMap方法,因此LinkedHashSet的实现非常简单,这里不再赘述。
1 | public class LinkedHashSet<E> |