一.hashmap基础
1.hashmap的node
-
node是一个节点
-
node存放元素的单元
2.hashmap的容量
-
初始容量为16,每次扩容为原来的两倍
3.hashmap的负载因子
-
负载因子为0.75f
-
默认的阈值为12
-
太大会造成多线程问题
-
太小会造成空间浪费
4.hashmap的hash()算法
-
指的是两次扰动
-
第一次扰动hash方法的时候
-
确认数组下标的时候
-
-
扰动的目的
-
是为了让hashmap
-
5.HashMap里面的hash()返回值
-
第一次扰动的值
二.hashmap的数组+链表/树问题
1.hashmap为什么引入链表
-
因为减少查询的速度。
2.为什么jdk1.8会引入红黑树呢
-
防止一条链表上的速度过多,增加查询时间。
3.hashmap为什么一开始不就使用红黑树?
-
数据量少的时候链表和红黑树的查询时间复杂度的区别不大。并且红黑树会占用更多的空间。
4.HashMap的底层数组取值的时候,为什么不用取模
,而是&
-
&也可以达到取模的效果
-
在计算机的底层,&方法比取模要快
5.数组的长度为什么是2的次幂
-
(n-1)&hash (key)
-
因为HashMap使用的方法很巧妙,他通过hash&(table.length-1)来获得该对象的保存位,前面说过HashMap的底层数组的长度总是2的n次方,这是HashMap在速度上的优化。当length总是2的n次方时,hash&(length-1)运算等价于对length取模,也就是hash%length,但是&比%具有更高的效率,比如n%32=n&(32-1)
三、hashmap里面的源码
1.HashMap的put()
2.HashMap的扩容原理
-
1.7的扩容原理(数组+链表)
-
1.8的扩容原理(数组+链表+红黑树)
-
第一次扩容
-
赋值初始容量:16 初始阈值:12
-
-
第二次扩容
-
当超过阈值的时候进行 并且容量扩大为原来的一倍,阈值同样扩大为原来的一倍 阈值 = 容量 * 负载因子
-
为什么达到阈值的时候扩容?
-
如果多线程的情况下,如果多个线程同时添加元素,如果达到容量在扩容,可能导致一个线程的元素无法添加进去。
-
-
为什么负载因子为0.75
-
如果太大会出现多线程的情况 如果太小了,可能会造成空间浪费
-
-
-
3.第一次resize方法做了什么?
-
赋值初始容量为16
-
赋值初始阈值为12,0.75f\
-
4.扰动的目的(两次扰动)
-
第一次扰动:
-
-
-
第二次扰动:
-
-
-
使得数字变小,让i在一定的范围之内
-
使得数字分布的更加均匀
5.值的覆盖