欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LinkedHashMap理解

程序员文章站 2022-07-12 18:32:30
...

注: 下面的源码理解均基于jdk1.8的源码

 

   HashMap是常用的数据集合,但是是无序, LinkedHashMap就是在HashMap上进行的一种扩展,在HashMap特性的基础上增加了有序这个特性(还可以根据最新使用自动排序)设计十分巧妙

 

   1 LinkedHashMap继承自HashMap

    

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
{

   2 LinkedHashMap 每个节点Node

    

    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);
        }
    }

    LinkedHashMap 的node继承了HashMap的node,在原来的基础上增加了before和after引用,实现了双向链表

 

   3 LinkedHashMap 存储结构还是HashMap的数组,每个node通过链表链接,LinkedHashMap 并没有重新put方法,而是在newNode()方法,与HashMap不同的是在HashMap新加节点的基础上(给数组index对应的赋值),设置了after,before引用,形成了链表

 

   

    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }

 

 

   4 LinkedHashMap  get方法进行了重新,不过在不使用accessOrder的时候实现还是HashMap的实现,直接使用hash获取index

    

    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;
    }

  

 

  5 遍历LinkedHashMap  jdk1.8提供的forEach是直接遍历链表,1.8之前的写法entrySet()进行遍历, LinkedHashMap 重写了entrySet()方法

   

    public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
    }

   返回的是一个有序的LinkedEntrySet,确保返回的数据是有序的

 

 

   总结: 感觉linkedHashMap的扩展做的很巧妙,既不失HashMap的特性,有巧妙的扩展出了新特性,这也是我们自己代码设计可以借鉴的地方