您的位置:首页 > 编程语言 > Java开发

Java-Collection源码分析(八)——LinkedHashMap

2017-09-27 21:42 405 查看

一、LinkedHashMap数据结构

LinkedHashMap是建立在HashMap的数组、链表和红黑树的基础上,添加了一个双向循环列表,将HashMap中的元素链接起来。

static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}

继承自HashMap中的next是用于维护HashMap指定table位置上连接的node的顺序的。



before、after是用于维护Entry(继承自HashMap中的Node)插入的先后顺序的。



二、底层操作

2.1 linkNodeLast():

private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}


2.2 transferLinks():

应用src链接到dst,用dst替换src。

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> a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}



2.3 afterNodeRemoval():

取消链接节点,但是没有删除节点,不利于JVM进行垃圾回收

void afterNodeRemoval(Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)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;
}


2.4 afterNodeInsertion()

可能删除长者
void afterNodeInsertion(boolean evict) {
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;

4000
removeNode(hash(key), key, null, false, true);
}
}

2.5 afterNodeAccess()

将节点移动到最后
void afterNodeAccess(Node<K,V> e) {
LinkedHashMap.Entry<K,V> last;
//若访问顺序为true,且访问的对象不是尾结点
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)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;
}
}



三、实现的主要方法

通过调用底层操作完成。

//如果此映射将一个或多个键映射到指定的值,则返回true。
public boolean containsValue(Object value) {
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
//返回指定键映射到的值,如果此映射不包含键的映射,则返回null。
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
//返回指定键映射到的值,如果此映射不包含键的映射,则返回defaultValue。
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null) //调用父类HashMap中的getNode方法
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
//从此地图中删除所有的映射。
public void clear() {
super.clear();
head = tail = null;
}
//如果此地图应删除其最老的条目,则返回true。
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: