LinkedHashMap.md 修缮部分内容

pull/56/head
AmyliaY 5 years ago
parent 60ac0fc12d
commit 11eaca0447

@ -1,13 +1,13 @@
HashMap 大家都清楚,底层是 数组 + (红黑树 / 链表)**元素是无序的**,而 LinkedHashMap 则比 HashMap 多了这一个功能并且LinkedHashMap 的有序可以按两种顺序排列一种是按照插入的顺序一种是按照访问的顺序初始化LinkedHashMap对象时设置accessOrder参数为true而其内部是靠 建立一个双向链表 来维护这个顺序的,在每次插入、删除后,都会调用一个函数来进行 双向链表的维护,这也是实现 LRU Cache 功能的基础。 HashMap 大家都清楚,底层是 数组 + (链表 / 红黑树)**元素是无序的**,而 LinkedHashMap 则比 HashMap 多了这一个功能并且LinkedHashMap 的有序可以按两种顺序排列一种是按照插入的顺序一种是按照访问的顺序初始化LinkedHashMap对象时设置accessOrder参数为true而其内部是靠 建立一个双向链表 来维护这个顺序的,在每次插入、删除后,都会调用一个函数来进行 双向链表的维护,这也是实现 LRU Cache 功能的基础。
先说几个比较重要的结论,大家可以根据这些结论从后面的源码解析中 得到证据。 先说几个比较重要的结论,大家可以根据这些结论从后面的源码解析中 得到证据。
1. LinkedHashMap 继承了 HashMap所以和 HashMap 的底层数据结构是一样的,都是数组+链表+红黑树,扩容机制也一样; 1. LinkedHashMap 继承了 HashMap所以和 HashMap 的底层数据结构是一样的,都是数组+链表+红黑树,扩容机制也一样;
2. LinkedHashMap 通过双向链表来维护数据的顺序 2. LinkedHashMap 是通过双向链表来维护数据的,与 HashMap 的拉链式存储不一样
3. LinkedHashMap 存储顺序与添加顺序默认是一样得,同时可以根据 accessOrder参数 来决定是否在访问时移动元素,以实现 LRU 功能。 3. LinkedHashMap 存储顺序与添加顺序是一样得,同时可以根据 accessOrder参数 来决定是否在访问时移动元素,以实现 LRU 功能。
```java ```java
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> { public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
/** /**
* 在 HashMap.Node节点 的基础上增加了 “前继节点” 和 “后继节点” 这种双向链表的功能特性 * 在 HashMap.Node节点 的基础上增加了 “前继节点” 和 “后继节点” 这种双向链表的功能特性
*/ */
@ -22,19 +22,19 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
* 记录这个 LinkedHashMap容器的 头节点 * 记录这个 LinkedHashMap容器的 头节点
*/ */
transient LinkedHashMap.Entry<K,V> head; transient LinkedHashMap.Entry<K,V> head;
/** /**
* 记录这个 LinkedHashMap容器的 尾节点 * 记录这个 LinkedHashMap容器的 尾节点
*/ */
transient LinkedHashMap.Entry<K,V> tail; transient LinkedHashMap.Entry<K,V> tail;
/** /**
* 是否根据访问 进行排序true为是可通过构造方法进行设置 * 是否根据访问 进行排序true为是可通过构造方法进行设置
*/ */
final boolean accessOrder; final boolean accessOrder;
// 下面是一些私有的内部公用方法 // 下面是一些私有的内部公用方法
// 将元素连接到链表尾部 // 将元素连接到链表尾部
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) { private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail; LinkedHashMap.Entry<K,V> last = tail;
@ -46,7 +46,7 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
last.after = p; last.after = p;
} }
} }
// apply src's links to dst // apply src's links to dst
private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) { private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) {
LinkedHashMap.Entry<K,V> b = dst.before = src.before; LinkedHashMap.Entry<K,V> b = dst.before = src.before;
@ -60,22 +60,22 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
else else
a.before = dst; a.before = dst;
} }
// 下面是一些 重写的 HashMap 的 hook methods其中 afterNodeInsertion、afterNodeRemoval // 下面是一些 重写的 HashMap 的 hook methods其中 afterNodeInsertion、afterNodeRemoval
// afterNodeAccess及方法在每次插入、删除、访问后都会回调 用来维护双向链表 // afterNodeAccess及方法在每次插入、删除、访问后都会回调 用来维护双向链表
void reinitialize() { void reinitialize() {
super.reinitialize(); super.reinitialize();
head = tail = null; head = tail = null;
} }
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) { Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p = LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e); new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p); linkNodeLast(p);
return p; return p;
} }
Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) { Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
LinkedHashMap.Entry<K,V> t = LinkedHashMap.Entry<K,V> t =
@ -83,21 +83,21 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
transferLinks(q, t); transferLinks(q, t);
return t; return t;
} }
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) { TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next); TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
linkNodeLast(p); linkNodeLast(p);
return p; return p;
} }
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) { TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next); TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next);
transferLinks(q, t); transferLinks(q, t);
return t; return t;
} }
// 在删除元素之后,将元素从双向链表中删除 // 在删除元素之后,将元素从双向链表中删除
void afterNodeRemoval(Node<K,V> e) { // unlink void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p = LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
@ -111,8 +111,8 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
else else
a.before = b; a.before = b;
} }
// 可用于删除最老的元素 // 可用于删除最老的元素
void afterNodeInsertion(boolean evict) { // possibly remove eldest void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first; LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) { if (evict && (first = head) != null && removeEldestEntry(first)) {
@ -120,8 +120,12 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
removeNode(hash(key), key, null, false, true); removeNode(hash(key), key, null, false, true);
} }
} }
// 是否删除 最近最少使用的元素
// 在访问元素之后,将该元素放到双向链表的尾巴处 protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
// 在访问元素之后,将该元素放到双向链表的尾巴处
void afterNodeAccess(Node<K,V> e) { // move node to last void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last; LinkedHashMap.Entry<K,V> last;
if (accessOrder && (last = tail) != e) { if (accessOrder && (last = tail) != e) {
@ -146,14 +150,14 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
++modCount; ++modCount;
} }
} }
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException { void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) { for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
s.writeObject(e.key); s.writeObject(e.key);
s.writeObject(e.value); s.writeObject(e.value);
} }
} }
/** /**
* 跟 HashMap 的构造方法没啥区别,初始容量、扩容因子 用以减少resize和rehash提升容器整体性能 * 跟 HashMap 的构造方法没啥区别,初始容量、扩容因子 用以减少resize和rehash提升容器整体性能
*/ */
@ -161,12 +165,12 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
super(initialCapacity, loadFactor); super(initialCapacity, loadFactor);
accessOrder = false; accessOrder = false;
} }
public LinkedHashMap(int initialCapacity) { public LinkedHashMap(int initialCapacity) {
super(initialCapacity); super(initialCapacity);
accessOrder = false; accessOrder = false;
} }
/** /**
* 注意accessOrder参数默认为false如果想使用 LRU机制记得设为 true * 注意accessOrder参数默认为false如果想使用 LRU机制记得设为 true
*/ */
@ -174,13 +178,13 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
super(); super();
accessOrder = false; accessOrder = false;
} }
public LinkedHashMap(Map<? extends K, ? extends V> m) { public LinkedHashMap(Map<? extends K, ? extends V> m) {
super(); super();
accessOrder = false; accessOrder = false;
putMapEntries(m, false); putMapEntries(m, false);
} }
/** /**
* 使用这个构造方法 设置accessOrder * 使用这个构造方法 设置accessOrder
*/ */
@ -188,7 +192,7 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
super(initialCapacity, loadFactor); super(initialCapacity, loadFactor);
this.accessOrder = accessOrder; this.accessOrder = accessOrder;
} }
/** /**
* 是否包含指定元素 * 是否包含指定元素
*/ */
@ -200,7 +204,7 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
} }
return false; return false;
} }
/** /**
* 获取指定key对应的value如果accessOrder为true会回调afterNodeAccess方法 * 获取指定key对应的value如果accessOrder为true会回调afterNodeAccess方法
* 将元素放到队尾 * 将元素放到队尾
@ -213,9 +217,9 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
afterNodeAccess(e); afterNodeAccess(e);
return e.value; return e.value;
} }
/** /**
* {@inheritDoc} * 根据 key 获取对应的 value如果key不存在则返回给定的默认值 defaultValue
*/ */
public V getOrDefault(Object key, V defaultValue) { public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e; Node<K,V> e;
@ -224,8 +228,8 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
if (accessOrder) if (accessOrder)
afterNodeAccess(e); afterNodeAccess(e);
return e.value; return e.value;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -233,7 +237,7 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
super.clear(); super.clear();
head = tail = null; head = tail = null;
} }
/** /**
* 获取key的set集合 * 获取key的set集合
*/ */
@ -245,7 +249,7 @@ public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
} }
return ks; return ks;
} }
/** /**
* 返回 键值对 的Set集合 * 返回 键值对 的Set集合
*/ */

Loading…
Cancel
Save