HashMap集合
HashMap为Key-Value键值对存储的集合,本文不会说出HashMap所有的原理,尤其是红黑树的原理,我没去看,太麻烦了,其他的我觉得也够用了!一起来看!墨迹起来。。。
关键字段及含义
//Map默认的开发的容量大小16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//最大容量2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
//负载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//没看
static final int TREEIFY_THRESHOLD = 8;
//没看
static final int UNTREEIFY_THRESHOLD = 6;
//没看
static final int MIN_TREEIFY_CAPACITY = 64;
1. 为什么默认16个长度?
查询了好多文章,没有一个特别有说服力的,做一个简单的总结吧,加上个人想法!!
1.1 先说为什么容量一直是2的N次方?
第一点是2的N次方,可以保证Hash值的二进制位都是1,HashMap在计算元素索引的时候,代码是这个样子滴:(n - 1) & hash,假设n=16,那么n-1=1111,可以保证n-1的二进制数都是1。为什么要保证都为1呢?这就涉及到一个概率的问题,也就是常说的为了HashMap中的元素能够均匀的分布到每个槽位上,至于算法概率上,不太好举例子,只能做一个简单的假设:
- 假如新加入一个元素,Key的hash值的后四位为1001,那么与1111做运算,1001 & 1111 = 1001;
- 再加入一个元素,key的hash值后四位是1011,做运算,1011 & 1111 = 1011
- 可以知道,这两次的索引计算结果不同。再看下面的假设
- 假设我们规定Hash的默认长度为10,那么10-1=9=1001
- 然后我们分别看一下计算结果
长度 key的hash值 结果
1001 1101 1001
1001 1011 1001
可以看出来,不同的hash值,计算的结果一样,这就是一个概率的问题,为了尽量让元素均匀分布,如果长度值为16,那么二进制 全是1,则可以缩小索引碰撞的几率。
1.2 为什么是16长度,为什么不是4、32、64?
这就是一个“合适”的问题,可能觉得4太小,32有点浪费!其他我想不出来有什么原因了!4的话,没加入几个元素就要再次扩容,32的话,不一定有这么多元素会被设置到map中,所以取了16作为默认长度。
2. 负载因子作用是什么?为什么是0.75?
负载因子是为了计算阈值的,阈值就是Map扩充的一个判断值,当元素的数量达到阈值,会扩容。初始化时:阈值=负载因子*默认容量;扩容时:阈值=当前阈值<<1,即2倍
2.1为什么是0.75?
探讨这个问题,首先要知道如果负载因子大了或者小了会有什么问题!
1. 假如负载因子为1,那么会导致下面的情况:
Map中的元素达到当前Map的容量时才会扩容,那