前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LinkedHashMap详解

LinkedHashMap详解

作者头像
提莫队长
发布2019-02-21 11:35:09
6200
发布2019-02-21 11:35:09
举报
文章被收录于专栏:刘晓杰刘晓杰

LinkedHashMap中有一个重要的数据:

代码语言:javascript
复制
    // LinkedEntry就是一个双向链表。除了保存当前对象的引用外,还保存了其上一个元素 before 和下一个元素 after 的引用
    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;
        }
    }

接下来看源代码:

代码语言:javascript
复制
public class LinkedHashMap<K, V> extends HashMap<K, V> {
    // 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。
    transient LinkedEntry<K, V> header;

    /**
     * True if access ordered, false if insertion ordered.
     */
    private final boolean accessOrder;

    //添加到header的prv位置,作为新的tail
    @Override 
    void addNewEntry(K key, V value, int hash, int index) {
        LinkedEntry<K, V> header = this.header;

        // Remove eldest entry if instructed to do so.
        LinkedEntry<K, V> eldest = header.nxt;
        if (eldest != header && removeEldestEntry(eldest)) {
            remove(eldest.key);
        }

        // Create new entry, link it on to list, and put it into table
        LinkedEntry<K, V> oldTail = header.prv;
        LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(
                key, value, hash, table[index], header, oldTail);
        table[index] = oldTail.nxt = header.prv = newTail;
    }


    //这个方法和HashMap很类似,唯一需要注意的就是accessOrder那一句
    @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;
        }

        // Replace with Collections.secondaryHash when the VM is fast enough (http://b/8290590).
        int hash = 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))) {
                //如果按照读取顺序,那么要调整e节点的位置
                if (accessOrder)
                    makeTail((LinkedEntry<K, V>) e);
                return e.value;
            }
        }
        return null;
    }

    //取出e节点插入到header前面一个节点
    private void makeTail(LinkedEntry<K, V> e) {
        // 把e节点取出来
        e.prv.nxt = e.nxt;
        e.nxt.prv = e.prv;

        // 把e节点插入到header前面一个节点中
        LinkedEntry<K, V> header = this.header;
        LinkedEntry<K, V> oldTail = header.prv;
        e.nxt = header;
        e.prv = oldTail;
        oldTail.nxt = header.prv = e;
        modCount++;
    }
}

LinkedHashMap没有实现put方法,而是复写了HashMap中的put方法里面的addNewEntry

由此我们可以总结 1.添加一个数据。先找到数组中对应的index,然后把数据放到链表的最后位置。由于是双向链表,那么就等于放在header.prv 2.获取一个数据。先找到数组中对应的index,然后找到数据所在的位置。如果是按照读取顺序来排序的,那么还要将这个节点放到双向链表的最后一位(这个特性,可以实现LRU算法)

参考: http://wiki.jikexueyuan.com/project/java-collection/linkedhashmap.html http://blog.csdn.net/ns_code/article/details/37867985

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年02月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档