码迷,mamicode.com
首页 > 其他好文 > 详细

LinkedHashMa源码解析

时间:2020-11-08 16:49:51      阅读:16      评论:0      收藏:0      [点我收藏+]

标签:new   before   java   null   自己的   obj   获取   判断   class   

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

LinkedHashMa源码解析

标签:new   before   java   null   自己的   obj   获取   判断   class   

原文地址:https://www.cnblogs.com/rocker-pg/p/13926910.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!