HashMap(jdk1.8)

hashmap在1.8中是以数组+链表+红黑树的结构实现的,在数组中的存放位置是用hash属性&长度-1 去寻址的(因为长度是2的幂,加上寻址方式,方便扩容,扩容两倍后数据不在原来位置就在原来位置+原长度),允许key为null,但是只能有一个;value可以null,不限个数。

hashmap无参构造初始化时啥没有,只有put时才会调用resize()才会有长度,默认16

一接口

实现了

Map<K,V>, Cloneable, Serializable 接口

继承

AbstractMap类

二 内部一些属性

DEFAULT_INITIAL_CAPACITY 默认长度,16,2的幂,原因是为了扩容(后面说),寻址碰撞
MAXIMUM_CAPACITY 最大长度,2^30=1 073 741 824
DEFAULT_LOAD_FACTOR = 0.75f; 负载因子
TREEIFY_THRESHOLD = 8; 链表向红黑树转化的阀值
UNTREEIFY_THRESHOLD = 6;红黑树转化成链表的阀值
Node<K,V>[] table; node的数组,存放具体的值,
threshold 负载数量,容量*负载因子
size 长度。数组里放了多少个值

MIN_TREEIFY_CAPACITY=64  转为红黑树的时候最小长度

数组

size 记录长度

modCount记录操作数

还有静态内部类Node,存储数据,key,value,hash,next(链表,指向下一个数据)

hash(),

计算hash值,获取key.hashCode()^(key.hashCode()>>>16)(异或操作,计算快,key 为null返回0)

put() ,

1.首先判断table是否已经初始化,否则调用resize(),进行初始化。

2.获取key对应位置的值,null就实例化一个新的node放进去,如果不null,或取得数据判断hash是否相等equals,是的话取得当前值,不是的话就要遍历了,(简单的说就是看看当前位置是不是没有hash冲突,当前位置不是链表也不是红黑树)当前位置空就直接放进去;如果是红黑树,调用putTreeVal()方法;已经有值的话就是个链表,当前位置node.next赋值为当前对象,并进行判断链表长度达到8,转化成红黑树;

3.判断(++size > threshold),根据条件进行判断是否需要扩容(2倍)

4.treeifyBin()

转化红黑树的时候,table长度最少要到64

if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
    resize();
resize()

扩容,

1.初始扩容,默认16

2.已经是最大长度了,不在扩容。

3..长度没达到最大长度,*2 也没达到最大长度。扩容两倍

扩容是指重新构造一个新的数组(两倍原数组),将原数组遍历重新分配到新数组里,因为是两倍扩容,并且长度时2的幂,寻址时又是获取node.hash&(容量-1),使得数据不在当前位置就在原位置的2倍的地方,减少移动。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值