LinkedHashMap继承于HashMap,有HashMap的所有特性,除此之外LinkedHashMap维护了一个双重链表,这个链表定义了元素的访问顺序包括:插入顺序和访问顺序,默认为按照插入顺序
关于HashMap介绍参考以下
http://blog.csdn.net/nuannuandetaiyang/article/details/71108241
LinkedHashMap的构造函数
public LinkedHashMap() {
init();
accessOrder = false;//元素顺序,默认为插入顺序
}
public LinkedHashMap(int initialCapacity) {
//调用HashMap的构造方法
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public LinkedHashMap(int initialCapacity, float loadFactor) {
this(initialCapacity, loadFactor, false);
}
public LinkedHashMap(
int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor);
init();
this.accessOrder = accessOrder;
}
LinkedHashMap数组的每一项也针对HashMapEntry做了延伸,添加了一个指向后一个元素的nxt指针和前一个元素的prv指针
static class LinkedEntry<K, V> extends HashMapEntry<K, V> {
LinkedEntry<K, V> nxt;
LinkedEntry<K, V> prv;
/** Create the header entry */
LinkedEntry() {
super(null, null, 0, null);
nxt = prv = this;
}
/** Create a normal entry */
LinkedEntry(K key, V value, int hash, HashMapEntry<K, V> next,
LinkedEntry<K, V> nxt, LinkedEntry<K, V> prv) {
super(key, value, hash, next);
this.nxt = nxt;
this.prv = prv;
}
}
LinkedHashMap的数据读取
@Override public V get(Object key) {
/*
* This method is overridden to eliminate the need for a polymorphic
* invocation in superclass at the expense of code duplication.
*/
if (key == null) {
HashMapEntry<K, V> e = entryForNullKey;
if (e == null)
return null;
if (accessOrder)
makeTail((LinkedEntry<K, V>) e);
return e.value;
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
e != null; e = e.next) {
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
// 如果定义了LinkedHashMap的迭代顺序为访问顺序,则删除以前位置上的元素,并将最新访问的元素添加到链表表头。
if (accessOrder)
makeTail((LinkedEntry<K, V>) e);
return e.value;
}
}
return null;
}
/**
* Relinks the given entry to the tail of the list. Under access ordering,
* this method is invoked whenever the value of a pre-existing entry is
* read by Map.get or modified by Map.put.
*/
private void makeTail(LinkedEntry<K, V> e) {
// Unlink e
//从链表中删除当前元素
e.prv.nxt = e.nxt;
e.nxt.prv = e.prv;
//添加元素到链表头
// Relink e as tail
//得到头指针
LinkedEntry<K, V> header = this.header;
//临时保存header指向的prv元素
LinkedEntry<K, V> oldTail = header.prv;
e.nxt = header;
e.prv = oldTail;
oldTail.nxt = header.prv = e;
modCount++;
}
新增的节点插入过程见图示
整体跟HashMap的数据读取没多大区别,主要的区别在于会根据accessOrder的状态执行makeTail方法,