概述
不久前阅读了 HashMap 的源码,今天来看下 LinkedHashMap 的源码,LinkedHashMap 继承自 HashMap,然后在类中新增了 head、tail、accessOrder 三个字段,其中会将插入、删除的数据与 head、tail 这两个字段进行关联,也就是说 LinkedHashMap 通过 head、tail 来保留了插入时的顺序。在查询到某个节点时,如果 accessOrder 为 true ,便会将查询到的节点设置为尾节点。简单来讲如果 accessOrder 为 true,那么 LinkedHashMap 保留的便是访问顺序,从最早访问到最近访问,head--->tail 就是 最早访问--->最近访问;否则便是插入顺序, head--->tail 就是 最早插入--->最近插入。使用 LinkedHashMap 就可以用来一种缓存淘汰算法(LRU 算法)。该篇文章不会再逐行解读,而是注视了每个方法的具体用处。
源码
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
/**
* 继承自 HashMap.Node,新增了 before、after 记录插入顺序
*/
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry before, after;
Entry(int hash, K key, V value, Node next) {
super(hash, key, value, next);
}
}
private static final long serialVersionUID = 3801124242820219131L;
/**
* 最早被使用到的数据,使用到指的是插入或者访问,这取决于 accessOrder
*/
transient LinkedHashMap.Entry head;
/**
* 最近被使用到的数据
*/
transient LinkedHashMap.Entry tail;
/**
* 如果 accessOrder 为 true,保留的是访问顺序,否则代表的是插入数据的顺序
*
* @serial
*/
final boolean accessOrder;
/**
* 与尾节点进行关联
*/
private void linkNodeLast(LinkedHashMap.Entry p) {
LinkedHashMap.Entry last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
/**
* 将 src 节点替换为 dst 节点
*/
private void transferLinks(LinkedHashMap.Entry src,
LinkedHashMap.Entry dst) {
LinkedHashMap.Entry b = dst.before = src.before;
LinkedHashMap.Entry a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}
// 以下重写的是 HashMap 的钩子方法
/**
* 将当前对象重置到初始化状态
*/
void reinitialize() {
super.reinitialize();
head = tail = null;
}
/**
* 创建一个新节点并于尾节点关联
*/
Node newNode(int hash, K key, V value, Node e) {
LinkedHashMap.Entry p =
new LinkedHashMap.Entry(hash, key, value, e);
linkNodeLast(p);
return p;
}
/**
* 通过 p 节点复制一个新的节点,使用顺序也会复制
*/
Node replacementNode(Node p, Node next) {
LinkedHashMap.Entry q = (LinkedHashMap.Entry)p;
LinkedHashMap.Entry t =
new LinkedHashMap.Entry(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
/**
* 创建一个新的红黑树节点,并关联尾节点
*/
TreeNode newTreeNode(int hash, K key, V value, Node next) {
TreeNode p = new TreeNode(hash, key, value, next);
linkNodeLast(p);
return p;
}
/**
* 通过 p 节点复制一个新的红黑树节点,使用顺序也会复制
*/
TreeNode replacementTreeNode(Node p, Node next) {
LinkedHashMap.Entry q = (LinkedHashMap.Entry)p;
TreeNode t = new TreeNode(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
/**
* 移除数据后的回调方法,跟记录使用顺序的节点解除关联
*/
void afterNodeRemoval(Node e) {
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}
/**
* 插入数据后的回调方法,有可能会移除最早被使用的数据(淘汰策略)
* 在 evict 为 true 的情况下且调用 removeEldestEntry 方法
* 返回 true 的情况下,其中 evict 是在插入数据的时候传入的参数,
* 如果 evict 代表的是 false,则表示第一次插入数据,也就无需
* 淘汰,而 removeEldestEntry 是一个可以进行重写的方法,用来
* 判断是否需要淘汰数据。
*/
void afterNodeInsertion(boolean evict) {
LinkedHashMap.Entry first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
/**
* 查询回调方法,如果 accessOrder 为 true 则将被访问的数据移动到尾节点
*/
void afterNodeAccess(Node e) {
LinkedHashMap.Entry last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
// 重写 HashMap 的方法,保证 LinkedHashMap 的使用顺序
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
for (LinkedHashMap.Entry e = head; e != null; e = e.after) {
s.writeObject(e.key);
s.writeObject(e.value);
}
}
/**
* 构造函数,调用 HashMap 的构造,并设置 accessOrder 为 false
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
/**
* 构造函数,调用 HashMap 的构造,并设置 accessOrder 为 false
*/
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
/**
* 默认构造函数,调用 HashMap 的构造,并设置 accessOrder 为 false
*/
public LinkedHashMap() {
super();
accessOrder = false;
}
/**
* 构造函数,调用 HashMap 的构造,并设置 accessOrder 为 false
*/
public LinkedHashMap(Map extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
/**
* 构造函数,调用 HashMap 的构造,指定链表数组长度、负载系数以及 accessOrder。
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
/**
* 重写了 HashMap 的方法,直接记录使用顺序的链表
*/
public boolean containsValue(Object value) {
for (LinkedHashMap.Entry e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
/**
* 重写了通过 key 查询 value 的方法,并回调
*/
public V get(Object key) {
Node e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
/**
* 重写方法,并回调
*/
public V getOrDefault(Object key, V defaultValue) {
Node e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
/**
* 重写,清空 head、tail 节点
*/
public void clear() {
super.clear();
head = tail = null;
}
/**
* 实现者重写该方法,判断是否需要移除老数据,该方法会在插入数据的回调方法中被调用
*/
protected boolean removeEldestEntry(Map.Entry eldest) {
return false;
}
/**
* 返回 map 中 key 的 set 集合
*
* @return a set view of the keys contained in this map
*/
public Set keySet() {
Set ks = keySet;
if (ks == null) {
ks = new LinkedKeySet();
keySet = ks;
}
return ks;
}
/**
* key 的 set 集合类
*/
final class LinkedKeySet extends AbstractSet<K> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator iterator() {
return new LinkedKeyIterator();
}
public final boolean contains(Object o) { return containsKey(o); }
public final boolean remove(Object key) {
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer super K> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.key);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
/**
* 返回一个集合,里面包含了 map 中所有的 value
*
* @return a view of the values contained in this map
*/
public Collection values() {
Collection vs = values;
if (vs == null) {
vs = new LinkedValues();
values = vs;
}
return vs;
}
/**
* value 集合类
*/
final class LinkedValues extends AbstractCollection<V> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator iterator() {
return new LinkedValueIterator();
}
public final boolean contains(Object o) { return containsValue(o); }
public final Spliterator spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED);
}
public final void forEach(Consumer super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
/**
* 返回一个 set 集合,里面包含了 map 中所有的 key value 映射
*/
public Set> entrySet() {
Set> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}
/**
* Key Value 映射集合类
*/
final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator> iterator() {
return new LinkedEntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry,?> e = (Map.Entry,?>) o;
Object key = e.getKey();
Node candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry,?> e = (Map.Entry,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer super Map.Entry> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
// 重写 Map 定义的方法
/**
* 遍历,遍历的是记录使用顺序的链表
*/
public void forEach(BiConsumer super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
/**
* 遍历 map,通过 function 函数对每个 key value 进行处理生成新的 value 并设置,遍历
* 的是记录使用顺序的链表
*/
public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
if (function == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
e.value = function.apply(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
//以下是 Key、Value 和记录 Key Value 映射关系的迭代器
abstract class LinkedHashIterator {
LinkedHashMap.Entry next;
LinkedHashMap.Entry current;
int expectedModCount;
LinkedHashIterator() {
next = head;
expectedModCount = modCount;
current = null;
}
public final boolean hasNext() {
return next != null;
}
final LinkedHashMap.Entry nextNode() {
LinkedHashMap.Entry e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
current = e;
next = e.after;
return e;
}
public final void remove() {
Node p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}
}
final class LinkedKeyIterator extends LinkedHashIterator
implements Iterator<K> {
public final K next() { return nextNode().getKey(); }
}
final class LinkedValueIterator extends LinkedHashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class LinkedEntryIterator extends LinkedHashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry next() { return nextNode(); }
}
}
复制代码