集合专区---第6集(LinkedHashMap)

1 背景

  1. LinkedHashMap继承了HashMap
  2. LinkedHashMap<K,V>:HashMap是以key-value形式存储数据的
  3. extends HashMap<K,V>:继承了HashMap,哈希表部分的功能和HashMap相似。
    implements Map<K,V>:实现了Map。HashMap已经继承了Map接口,为什么LinkedHashMap还要实现Map
     
  4. LinkedHashMap还维护着一个双重链接链表

2 结构

  1. 因为继承了HashMap,所有结构上也是链表+数组+红黑树
  2. 同时因为LinkedHashMap因为是有顺序的,它包含一个贯穿于所有entry的双重链接列表。
  3. 大部分方法都是继承HashMap,但是也有部分关键方法是重写的

3 重写方法详解

1 LinkedHashMap 中数组中的链表节点元素对象结构

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;//前一个位置与后一个位置的节点,主要用来记载LinkedHashMap中的前后位置的节点
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

2 put是继承了父类HashMap,但是如果和父类完全一样,那肯定是不可能的,所有肯定对方法有重写

重写的方法1 :

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);  //该方法的作用是修改双向列表,来保持我们LinkedHashMap中记录的元素位置
    return p;
}

 newNode()方法被重写了,调用方式:(put(父类)---->putVal(父类)--->newNode(子类重写))

重写的方法2 :

TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
    TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
    linkNodeLast(p);//该方法的作用是修改双向列表,来保持我们LinkedHashMap中记录的元素位置
    return p;
}
newNode()方法被重写了,调用方式: put(父类)---->putVal(父类)---->putTreeVal(父类)---->newTreeNode(子类重写)

重写的方法3 :

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

因为LinkedHashMap中有2种 排序方式:插入的顺序(accessOrder=false)\ 访问顺序(accessOrder=true)

accessOrder:通过构造方法来设置

重写排列双向链表

双向链表(插入的时候调用下面方法) 指针问题:

private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
    LinkedHashMap.Entry<K,V> last = tail;
    tail = p;
    if (last == null)
        head = p;
    else {
        p.before = last;
        last.after = p;
    }
}

当第一次添加元素的时候 , 头节点和尾节点 都为 这个新元素

当不是第一次添加元素的时候 把尾节点的值设置为新来的元素,然后把旧的尾节点的after指向新的尾节点,把新节点的before指向酒旧的尾节点  


 

/**
 * The head (eldest) of the doubly linked list.
 */
transient LinkedHashMap.Entry<K,V> head;

/**
 * The tail (youngest) of the doubly linked list.
 */
transient LinkedHashMap.Entry<K,V> tail;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值