首页 > 技术文章 > HashMap学习 — 单向列表转化为双向列表

seeall 2020-07-08 20:33 原文

一、概览

  HashMap的某个桶位如果存储的是单向列表,当向这个桶位继续插入一个元素的时候,这个桶位元素的数量超过

  

  8时,单项列表会转化为红黑树(同时是一个双向列表,jdk1.8之后),且会先转化为双向列表:

  

 

二、转化过程

  1,运行如下程序,使map底层数组的某个桶位的单向列表”开始“转化为红黑树

  

   按道理,当map-put的元素超过 8*100 = 800时才会扩容数组,所以,当map.put(65, "65")时,table[1]的位置将会是:

  

  此时,table[1]的元素数量(9个)超过8(TREEIFY_THRESHOLD),这个单向列表会被转化为红黑树,但是受

  

  这个数字的影响,数组的长度(现在为8)只有扩容到64之后,才会将单向列表会被转化为红黑树;扩容的过程:参考(参考http:还没写好)。

  当map.put(513, "513")时,table[1]的位置将会是:

  

 

   此时,table[1]的元素数量(9个)超过8(TREEIFY_THRESHOLD),这个单向列表”将会“被转化为红黑树。

 

  2,单向列表转化为红黑树

  先转化为双向链表,双向链表转化为红黑树,参考:http:还没有写好;

  jdk1.8 - HashMap源代码如下红框所示:

  

  e:tab[1],是一条单向链表,如上面数组的那个示意图,节点都是Node类型,随着单向列表不断的递进,指向的当前单向列表的节点;

  hd:head?头部节点,双向列表的头部节点,节点是TreeNode类型;

  tl:tail?尾部节点,双向列表的尾部节点,节点是TreeNode类型;

  p:e当前指向的单向列表的节点转化为TreeNode类型后的节点;

 

  2.1,Node和TreeNode的联系与区别

   Node: 

 

  TreeNode:, 

 

  TreeNode是Node的子类,也就是说TreeNode含有Node的所有属性;

  Node是一个含有next属性的单向列表,TreeNode是一个含有next(继承自Node)、prev属性的双向链表,同时TreeNode还是一个含有left、right、parent属性的二叉树,同时TreeNode还是一个含有boolean red属性的红黑树(在二叉树的基础上)。

 

  2.2,单向列表开始转化为双向链表

  p的来源:

  1,第一次循环

  

   2,第二次循环

  

  3,第三次循环

  

   4,以此类推

  总结下来,就是:

  A、让单向列表递进,使用局部变量(中间变量)e指向递进过程中的某个节点;

  B、使用中间变量p,根据步骤A中的e构造出一个双向链表的节点(当前还没有挂到双向列表上);

  C、如果双向链表的尾部为空,即双向链表没有任何节点,则让步骤B中的p既作为头也作为尾;

    如果双向链表的尾部不为空:则需要将步骤B中的p挂到双向列表的尾部;

  D、最后,由于双向列表的尾部发生了变化,需要将tl指向新的尾部节点。

 

  

 

推荐阅读