首页 > 其他分享 >HashMap链表树化究竟是怎样的?

HashMap链表树化究竟是怎样的?

时间:2023-08-29 15:44:33浏览次数:38  
标签:hash HashMap tab 树化 value 链表 key null

网上一直看到两种说法:

1.数组长度大于64且当链表长度>8时,链表转换为红黑树;

2.数组长度大于64且当链表长度≥8时,链表转换为红黑树。

 

上源码,主要是putVal()函数

/**
 * Implements Map.put and related methods.
 *
 * @param hash hash for key
 * @param key the key
 * @param value the value to put
 * @param onlyIfAbsent if true, don't change existing value
 * @param evict if false, the table is in creation mode.
 * @return previous value, or null if none
 */
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
          // 关键点,这里e=p.next而不是e=p;因此当binCount=0时,e为当前节点指向的下一个节点 if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }

首先在put时对多种情况进行了分别处理,依次是:

1.hashtable本身为空

2.需要存入的节点hash后所在位置无值

3.需要存入的存入节点与已有节点key相同直接替换原值

4.根据长度判断是否需要树化,这里

然后是转换红黑树的函数treeifyBin()

/**
* Replaces all linked nodes in bin at index for given hash unless
* table is too small, in which case resizes instead.
*/
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
TreeNode<K,V> hd = null, tl = null;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}

标签:hash,HashMap,tab,树化,value,链表,key,null
From: https://www.cnblogs.com/fulaien/p/17664975.html

相关文章

  • 手撕代码之链表
    文章目录一、反转链表(leetcode206)二、两个链表的交点(leetcode160)三、链表的中间结点(leetcode876)四、判断链表是否存在环(leetcode141)五、输出链表环的入口结点(leetcode142)六、删除链表中倒数第k个节点(leetcode19)七、合并两个排序链表(leetcode21)八、O(1)时间删除链表中的一个......
  • 快排及链表排序
    文章目录一、普通的快排二、链表的创建三、链表的冒泡排序四、链表快排五、链表归并排序一、普通的快排voidQuickSort(vector<int>&vec,intlow,inthigh){ intpivot=vec[low];//选择第一个元素作为枢纽元 //mid总是指向最后一个比枢纽元小的位置,当需要交换元素时,先......
  • 876 , 链表的中间节点
    https://leetcode.cn/problems/middle-of-the-linked-list/ 使用快慢指针1lassSolution{2publicListNodemiddleNode(ListNodehead){3//排除为空情况4if(head==null){5returnnull;6}7//使用......
  • 实现-双向链表
    1/*2简介:双向链表,可在头尾实现插入和删除3注意:这个双向链表不形成环4作者:njit-sam(许言)5*/67#include<stdio.h>8#include<stdlib.h>9#include<string.h>1011typedefstructdouble_linked_list{12intindex;13struc......
  • ConcurrentHashMap存null的讨论
    ConcurrentHashMap存null的讨论参考:https://juejin.cn/post/7057696800739688479今天发现某公众号推送了ConcurrentHashMap为什么不允许存储key|value为null感觉写的有问题,好像是从互联网上抄的,于是做了搜索,发现上面参考给出的结论比较靠谱,核心还是二义性。即当存入<@Not......
  • ConcurrentHashMap为何不能插入null?HashMap为何可以?
    归纳来说就是两个问题:1.ConcurrentHashMap为什么key和value不能为null?2.ConcurrentHashMap能保证复合操作的原子性吗?1.ConcurrentHashMap为什么key和value不能为null?ConcurrentHashMap的key和value不能为null主要是为了避免二义性。null是一个特殊的值,表示......
  • 剑指Offer 25. 合并两个排序的链表
    题目链接:剑指Offer25.合并两个排序的链表题目描述:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。解法思路:在两链表向后遍历的过程中,哪个更小一点,哪个先放在合并后的链表中。最后哪个链表剩余,直接接在合并链表的后面即可。代码:/***Definit......
  • 剑指Offer 22. 链表中倒数第k个节点
    题目链接:剑指Offer22.链表中倒数第k个节点题目描述:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。解法思路:快慢指针:慢指针不动,快指针先走k步,然后快慢指针一起向后走,当快指针走到末尾时,慢指针所指的就是倒......
  • 用单链表解决约瑟夫问题 C语言实现
    编号为1,2,3,…,n的n个人按顺序针方向围坐一张圆桌旁,每个人手中持有一个密码(正整数)。首先输入一个正整数作为报数上限值m,然后,从第一个人开始按顺序针方向自1开始顺序报数,报到m的人离开桌子,并将他手中的密码作为新的m值,从顺序针方向的下一个就坐在桌旁的人开始重新从1报数,如此下去,直......
  • 用单链表实现一元多项式相加 C++代码
     #include<iostream>usingnamespacestd;/*结点的定义*/typedefstructLNode{floatcoef;intexp;structLNode*next;}LNode;typedefLNode*Polynomial;/*多项式的初始化*/voidinitDuoX(Polynomial&Px){Px=newLNode;......