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) {....}可以使其迭代的方式变为按访问时候的顺序。