HashMap的链表结构

代码如下

public class HashSet_ {
    public static void main(String[] args) {
        HashSet set = new  HashSet();
        //十二个对象在每一行的头部,使行数达到临界值,从而进行table数组扩容
        for (int i = 0; i <= 12; i++) {
            set.add(i);
        }
        //十二个对象在同一行,使某一行的链表排满,从而进行树化的过程
        for (int i = 0; i <= 12 ; i++) {
            set.add(new A(i));
        }
        System.out.println(set);
    }
}
class A{
    public int a;

    public A(int a) {
        this.a = a;
    }

//重写hashCode方法,让他落在同一链表中,以便实现链表树化
//类中的hashCode方法返回的值可以影响到他在hashMap中的位置
//当hashCode返回值相同的时候,就处在同一链表中(同一行)
    @Override
    public int hashCode() {
        return 100;
    }
}

1、HashMap链表中有三个比较重要的属性,table和threshold(阈值),loadFactor(加载因子)

2、table属性相当于把每一条链表再连起来的链

通俗一点来说就相当于一张表里的行,每一行都有一串数据,这一串数据就称为链表。tables的引用类型是Node[]对象数组,所以table属性保存第一个传进来的对象,相当于每一行的头部对象都保存在table这个对象数组里面,每一行中的每个对象又挂载到上一个对象的next属性中形成一条链

从debug里面的属性可以看出,table一开始为空的,调用了add方法新增一个对象后,扩容了16个空间,相当于有了16行,并把这个对象分配给table[0]的位置上(第一行首位)

相当于 table[0] = Integer 0 ;后续如果有哈希值是和这个对象相同的元素加入,就在这个链表后面的追加。

3、threshold(阈值):链表的临界值

阈值 = table * loadFactor ,一开始table = null,传入第一个对象后Node[] table = new Node[16]创建一个链表空间,容量为16,可以容纳16条链表,后续添加的对象超过阈值12个之后进行链表空间的扩容,扩容大小为之前的两倍。注意:这12个对象并不一定要分布在每一行,把每一行占满再进行扩容,当某两个链表相加的元素大于12也开始扩容

扩容前:

 扩容后:

 示意图

 

 以上为table属性容量不够的情况(行不够用)的扩容方法,那列不够用的情况呢?

1、当链表中的元素等于8时,每新增加一个元素,就先进行数组的扩容,扩容到32,再增加就扩容到64,当增加到64的时候,不在增加,且把链表中的元素树化(红黑树)

链表元素未到8时 ,位置在table[4]

等于8时,进行数组的扩容table[16]变成table[32]

 链表元素每增加1,都扩大一倍,当table大小等于64时,table不再扩容,并且该链表也转移了位置

 当table的容量不再扩容,后续该链表还有元素要加入时,该链表会进行树化,该链表的类型会从Node变成TreeNode,从链表变成红黑树,有左节点和右节点

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值