hashmap知识点简单汇总

 

  1. HashMap扩容
    1. hashMap的底层数组的初始值是16,负载因子是0.75,扩容默认的是16*0.75=12,当要添加的元素如果添加后超过了12就开始扩容(不一定是12,看你new hashMap(int capacity)capacity是几,一般是12,就先说12吧),扩容是2倍,就是扩容的长度是原来的2倍
    2. 1.7的时候hashmap的底层是数组(桶)+链表,1.8的时候是数组+链表+红黑树

 

 

  1. hashMap可以存null,可以存无数null,但是null对应的value值只能是最新的一个,但是hashTable不行
  2. put方法

因为hashMap的key是不能相同的,如果put()的时候元素的key已经存在,那么value就用新值代旧值的方法,基本上所有的put方法就是根据这个原则来的

1.7的时候

先根据hash()方法求出要put进去的key的hash值,然后根据hash值与(组桶的长度-1)做取余运算得到要存放在的桶的位置【实际代码是indexFor()方法】,然后开始for循环比较这个桶以及这个桶下的链表下是否有值,有值先一个个比较当前桶下的元素的hash值和要put进去的key的hash值和equals()内容是不是相等,相等的话,把已经存在的key对应的value用新的value代替了,否则,直接添加此元素,如果此桶的位置上没有元素,那么也直接添加此元素======》添加的时候涉及到扩容,判断当前put的值之后数组的size是否超过了阈值的大小,如果超过了,那么就开始2倍的扩容,让Entry数组的长度*2,然后重新对要put的值进行rehash(),重新得到hash值,用新得到的hash值与数组的新长度进行取余运算,然后对新元素创建Entry()对象,使用CreateEntry()进行元素添加添加,最后把size++,即size+1

1.8的时候

因为1.8在new hashMap()的时候没有对底层的数组进行初始化,所以在put()元素的时候首先就是判断Node数组是否为null并且数组.size=0,如果是的话,对底层Node数组进行resize()初始化,设置集合阈值(扩容的临界值),集合capacity,负载因子,(一般集合capacity默认设为16,阈值为12,负载因子为0.75)然后进行hash(key)运算,hash运算进行了hash值与hash值右移16位的或运算(避免hash值重复),并且与数组长度进行取余运算得到桶位置,如果此桶的位置上没有元素,直接添加Node()节点,否则判断此桶位置上的元素是不是红黑树上的一个元素,如果是的话,执行添加TreeNode()节点操作,如果还不是的话,进行for循环,判断此桶位置上的元素的下一个位置是否有值,没有值的话,根据当前要添加的元素构造Node()节点,然后判断要添加的元素添加后是否超过阈值-1的值,(代码中实际方法是treeifyBin())如果超过,开始扩容,如果此桶位置上的下一个位置上有值,那么判断hash值和equals()内容是否相等,相等的话,直接用新值代替旧值

  • hashMap1.7和1.8的区别
  •  

 

 

为什么出现红黑树

  • 因为链表在查找元素的时候,其时间复杂度是O(n),不管你要查找的元素在链表的哪个位置,它都是从链表的第一个位置查找那个元素的,即有n个元素,那查找到指定的元素就是要经过n次遍历,即O(n),所以,链表不适合元素特别多的查找情况,而红黑树的查找元素的时间复杂度是O(logn)因为红黑树是有顺序的

为什么负载因子是0.75?

 ArrayList扩容时默认的容量大小为10,扩容时直接在满了容量的时候进行扩容,HashMap不是,是在负载因子的作用下,在16*0.75的作用下进行扩容的,不满的情况下扩容原因是为了减少链表情况的存在,如果负载因子过小,数组的利用率较低,如果是0.3,则16*0.3=4,在4的时候扩容的话,如果是16*0.9的话,会让链表产生的过多,所以使用

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值