Hash table and linked list implementation of the Map interface,with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.
LinkedHashMap实现了Map接口,继承于HashMap,与HashMap不同的是它维持有一个双链表,从而可以保证迭代时候的顺序。
public class TestLinkedHashMap {
public static void main(String[] args) {
Map<String,String> map = new LinkedHashMap<String,String>();
map.put("数学","数学老师");
map.put("化学","化学老师");
map.put("物理","物理老师");
map.put("生物","生物老师");
map.put("政治","政治老师");
for(Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}
}
可以看出LinkedhashMap在HashMap 基础上,用一个双向的链表维持的插入时候的顺序(默认,即accessOrder = false)。
public class TestLinkedHashMap {
public static void main(String[] args) {
//构造的时候 初始化容量为16,负载因子为0.75
//第三个参数为accessOrder ,即迭代的顺序。有按插入的顺序和访问时的顺序。
//默认为false,即按插入时候的顺序进行迭代。设置为true后,按访问时候的顺序进行迭代输出,即链表的最后一个元素总是最近才访问的。
Map<String,String> map = new LinkedHashMap<String,String>(16,0.75f,true);
map.put("数学","数学老师");
map.put("化学","化学老师");
map.put("物理","物理老师");
map.put("生物","生物老师");
map.put("政治","政治老师");
map.put("数学","数学老师");
for(Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}
}
此时调整链表如下:
LinkedHashMap部分源码:
//链表第一个元素
transient LinkedHashMap.Entry<K,V> head;
//链表最后一个元素,当accessOrder = true的时候,表示最近使用的一个元素
transient LinkedHashMap.Entry<K,V> tail;
//迭代方式,默认为false,即按插入时候的方式进行迭代
//若为true,即按访问时的顺序进行迭代
final boolean accessOrder;
//五种构造方法
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
//默认为false
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
//自定义accessOrder
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
......
//移除相应节点
void afterNodeRemoval(Node<K,V> e) { // unlink
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;
}
//插入相应节点
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
//accessOrder = true的时候,保证最后一个节点是最近使用的
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
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;
}
}
//get
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;
}
总结:
LinkedHashMap是基于HashMap实现的,对于HashMap有认识,理解LinkedHashMap应该不难.LinkedHashMap使用一个双向链表对键值度进行维护,创建LinkedHashMap的时候,默认accessOrder=false,迭代的时候为插入时候的顺序,只有第五种构造方法:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {....}
可以使其迭代的方式变为按访问时候的顺序。