HASHMAP 深度解析
前言
提示:为什么我们要读源码?工作中能用上吗?
JDK的源码的作者大部分是由这个专业上顶尖的人设计与实现的,我们阅读源码就是站在巨人的肩膀上去学习与理解。而且是这优秀的设计也是可以复用到我们实际工作中的,如hashmap中对桶位置的计算,其实我们也可以用到分库分表的设计,但在这之前我们一定要充分理解那能在实际设计中,本文主要介绍hashmap的经典设计并说明原理。
一、hashmap是什么?
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
二、经典设计
1.以原容量2倍进行扩容(为什么不是1.5位或者其它的倍数)
我们先给出结论再由结论去看是怎么实现的
1. 以2位的方式扩容,使HASH更加散列
2. 减少扩容时,Node的移动,既使发生移动也是 n位的移动.
代码如下(示例):
final Node<K,V>[] resize() {
....
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
....
return newTab;
}
这是hashmap扩容时重新计算KEY位置是以当前key的hash 与 容量取位与 下面我们实际举例:
试想如果是以1.5位扩容,是不是不能保证n-1的二进制每一们都没1 ,这样进行散列可能导致分部不均衡。
然后,如果进行扩容位移,也不能保证是不移动或者N/2移动。