用debug看HashMap

一直都是对HashMap的底层及扩容原理都没有很好的理解,所以就决定重新对HashMap的底层原理重新来梳理梳理。

HashMap这个扩容原理真的是众说纷纭,感觉就没有一个较为清楚,原来只知道的HashMap当链表的长度大于8 并且数组的长度大于64 链表才会转换成红黑树。但是一直没有去自我验证,今天我就来验证验证,此次我们使用的是JDK1.8:

/**
 * @author acoffee
 * @create 2021-08-23 11:02
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        HashSet set = new HashSet();

        for (int i = 1; i <= 12; i++) {
    
    //我们在这排deBug
            set.add(new Student(i));
        }
    }
}

class Student {
    
    
    private int age;

    public Student(int age) {
    
    
        this.age = age;
    }

    //重写hashCode 为了使所有的值挂在一个链表上
    @Override
    public int hashCode() {
    
    
        return 100;
    }
}

我们开始debug
在这里插入图片描述
我们可以看到此时table为空,这就意味着 当我们去创建Map的时候他是不会在底层创建长度为16的数组的。我们继续
在这里插入图片描述
从上述结果我们可以清楚的看到,当我我们第一次添加的时候,我们的数组长度就变成了16 ,并且我们添加的数据通过Hashcode计算在索引为4的位置。

因为接下来我们添加的hash值都是一样的,就都会挂在一个链子上,我们不再过多赘述,我们直接添加 8 个数据使 链表长度 到8,来看结果。
在这里插入图片描述
通过上图我们可以清楚的看到此时链表已经到8,我们继续添加
在这里插入图片描述
在这里插入图片描述

从上图可以看出我们将链表长度添加到9,此时从我们的框起来的位置可以看出,他还是一个链表,并没有变成树,但是当我们将debug框往下翻的时候,我们发现数组的长度变成了32。我们继续添加
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
此时我们发现数组的长度变成了64,而我们原本存放在4索引位置的链表 变到索引为36的位置,而且此时还是链表。我们继续添加:

在这里插入图片描述
在这里插入图片描述
这个时候我们就发现数组的长度不在改变了,但是如图所示Node结点变成了TreeNode结点,到此链表就转换成了红黑树。

所以在这里我们得出结论 HashMap中只有当链表的长度大于8并且数组的长度大于等于64 链表才会转换成红黑树。

还有就是Map第一次put底层才会创建一个长度为16 的数组。

完整过程:
当我们第一次调用HashMap的时候,它不会在底层创建一个长为16 的数组,而是当我们第一次put 的时候它就会创建一个长度为16的数组,我们一直拿数据往同一链表上挂(由于找hash值相同数据很难,所以 上述我们用了重写hashCode的方法) 直至长度为8,此时数组的长度还是16,我们发现这个长度为8的链表并没有转换成红黑树,而当我们继续往链表上添加数据,数组会扩容至原来的两倍(32),链表长度也会增长至9,继续往链表上添加数据,链表会继续增长至10,数组扩容为64,这个时候就满足了转红黑树的条件,继续添加,我们可以清楚的看到链表变成了红黑树。

Supongo que te gusta

Origin blog.csdn.net/weixin_44742328/article/details/119877842
Recomendado
Clasificación