LinkedHashMap

LinkedHashMap是HashMap的子类,保留HashMap特性并保证迭代顺序。它通过一个双向链表维护元素顺序,可按插入或访问顺序排列。构造函数默认按插入顺序排序。在key重复时,节点会被移到链表尾部,get()操作也可能触发此行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LinkedHashMap

简单介绍

        LinkedHashMap继承自HashMap,实现了Map接口,所以LinkedHashMap是在HashMap的基础上实现的,保留了HashMap的所有特征,唯一与HashMap不同的是,LinkedHashMap是可以保证数据的迭代顺序的(可以是访问顺序,也可以是插入顺序)
在这里插入图片描述

属性及构造函数

        LinkedHashMap的属性包括:

// 双向链表的头指针,指向第一个node节点
transient LinkedHashMap.Entry<K,V> head;
// 双向链表的尾指针,指向最后一个node节点
transient LinkedHashMap.Entry<K,V> tail;
// 标志位,为true时,表示按照访问顺序迭代,为false时,表示按照插入顺序迭代。
final boolean accessOrder;

        LinkedHashMap的构造函数有以下几种:

   public LinkedHashMap() {
        super();
        accessOrder = false;
    }
   
   public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }
   public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

   public LinkedHashMap(Map<? extends K, ? extends V> m) {
        super();
        accessOrder = false;
        putMapEntries(m, false);
    }
   public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }

        我们发现,LinkedHashMap默认是按照插入顺序来迭代的。

LinkedHashMap的相关方法

        首先,我们来看一看LinkedHashMap的插入操作,LinkedHashMap没有自己定义一个put(),而是直接使用了HashMap中的put(),所以,它的添加操作会HashMap是一致的。

            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }

        唯一不同的是这里,afterNodeAccess()在HashMap中是没有实现的,而LinkedHashMap则重写了这个方法

    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;
                // 由于要将节点移至双链表尾部,所以先将该节点的后驱节点置为null
            p.after = null;
            // 如果它的前驱为null,说明,前面没有节点,将头指针,指向它的后继节点。
            if (b == null)
                head = a;
            else
            // 调整节点顺序
                b.after = a;
            // 后继节点不为null时,重新调整前驱节点。
            if (a != null)
                a.before = b;
           // 如果待移动节点的后继节点为null,说明,待移动节点是双链表最后一个结点
            else
            // p之前就是尾指针 
                last = b;
                // 双向链表只有p一个结点,则p又是头结点也是尾节点
            if (last == null)
                head = p;
                // 否则 将p插入链表尾部。
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }

        这个方法,是在key出现重复时,调用的, 是将重复的key所对应的节点,放入到双链表的尾部。同时,在调用get()操作时,如果判断accseeOrder为true时,也会调用这个方法。

        其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多了一个双向链表,由于维护数据的迭代顺序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值