• LinkedHashMa源码解析


    LinkedHashMap(jdk 1.8.0_231)

    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
      	// 构建新的entry节点
      	LinkedHashMap.Entry<K,V> p =
        new LinkedHashMap.Entry<K,V>(hash, key, value, e);
      	// 将新的节点添加到双向链表的最后处
      	linkNodeLast(p);
      	return p;
    }
    
    // link at the end of list
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
      	// 获取尾节点
        LinkedHashMap.Entry<K,V> last = tail;
      	// 尾节点tail指向当前传入的节点p
        tail = p;
        if (last == null)
          	// 如果原先的尾节点为null的话,说明这是个size为0的map,
          	// 头节点指向当前传入的节点p,
          	// 此时,头节点head和尾节点tail都指向了当前传入的节点p
          
          	// 并且,此时head节点和tail节点,都没有自己的before和after节点
            head = p;
        else {
          	// 如果原先的尾节点不是null的话,
          	// 将当前传入的节点p的前一个节点before指向原先的尾节点last
            p.before = last;
          	// 将原先的尾节点last的后一个节点after指向当前传入的节点p,
          	// 此时就构成了双向链表,last的after指向p,p的before指向last
          
          	// 此时,p的before就是head,head的after就是p,head的before为null,p的after也是null
            last.after = p;
        }
    }
    
    public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
          	// 如果按照访问顺序排序的话
          	// 在node被访问后,走一下这个方法,给node排个序
            afterNodeAccess(e);
        return e.value;
    }
    
    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
      	// 将last指向原先的尾节点tail,
      	// last只被赋值了两次,
      	// 第一次是这里,last= tail,第二次是last = b
        if (accessOrder && (last = tail) != e) {
          	// 如果按照访问顺序排序,并且原先的尾节点tail不等于最近访问的节点e,
          	// 如果原先的尾节点tail等于最近访问的节点e的话,就不用往下继续了,本来也是要把最近访问的节点放到最后的
          	// 将最近访问的节点e赋给节点p,p的before赋给节点b,p的after赋给节点a,
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
          	// 将p的after设置为null
            p.after = null;
          
          	// 先判断b
            if (b == null)
              	// 如果p的前一个节点b是null的话,说明p和head指向同一个节点,
              	// 访问完p之后,将p的后一个节点a设置为头节点,没毛病
                head = a;
            else
              	// 如果p的前一个节点不是null的话,
              	// 将p的前一个节点b的after指向p的后一个节点a
                b.after = a;
          
          	// 再判断a
            if (a != null)
              	// 如果p的后一个节点a不是null的话,说明p不是尾节点,
              	// 将a的before指向b,构成双向链表
                a.before = b;
            else
              	// 如果p的后一个节点a是null的话,说明p和tail指向同一个节点,
              	// 将last指向p的前一个节点,last不和tail指向同一个节点了,
              	// 第二次是这里,last = b
                last = b;
          
          	
            if (last == null)
              	// 如果last等于null的话,
              	// 只能是last = b,而b本身是null,
              	// head,tail,p都是指向同一个节点,
              	// 所以head指向p
                head = p;
            else {
              	// 如果last不等于null的话,
              	// p的before指向last,也就是p的前节点指向原先的tail节点
                p.before = last;
              	// 原先的尾节点tail的after指向p,构成双向链表
                last.after = p;
            }
          
          	// 无论上面怎么操作,新的tail肯定是指向了p,
          	// 也就是最近访问的节点,放到链表的最后
            tail = p;
            ++modCount;
        }
    }
    
    void afterNodeRemoval(Node<K,V> e) { // unlink
      	// 获取到移除的p节点和前驱b后继a节点
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
      	// 将p从链表中断开
        p.before = p.after = null;
      
      	// 先判断b
        if (b == null)
          	// 如果p的前一个节点b为null,说明p自己就是头节点
          	// 移除p之后,p的后继节点a就是头节点了,没毛病
            head = a;
        else
          	// 如果p的前驱节点b不是null,
          	// 将p的前驱节点的after指向p的后继节点a
            b.after = a;
      	
      	// 再判断a
        if (a == null)
          	// 如果a为null的话,说明p为尾节点
          	// 移除p之后,p的前驱节点b和tail指向同一个节点
            tail = b;
        else
          	// 如果a不为null的话,说明p不是尾节点
          	// 将a的before指向p的前驱节点,构成双向链表
            a.before = b;
    }
    
  • 相关阅读:
    camp训练day2
    LCA板子题
    牛客多校第一场
    P1063 能量项链 区间DP
    64. Minimum Path Sum
    46. Permutations
    216. Combination Sum III
    62. Unique Paths
    53. Maximum Subarray
    22. Generate Parentheses
  • 原文地址:https://www.cnblogs.com/rocker-pg/p/13926910.html
Copyright © 2020-2023  润新知