LinkedHashMap源码探究

来源:互联网 发布:知乎什么话题最火 编辑:程序博客网 时间:2024/06/03 13:36

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

image
新增的节点插入过程见图示

整体跟HashMap的数据读取没多大区别,主要的区别在于会根据accessOrder的状态执行makeTail方法,

0 0