HashMap是我们在平时开发最常用的容器之一,但是我们有真正了解过他吗?他是线程安全的吗?他是以何种方式来存储的呢?为什么初始化的容器大小时2的n次幂呢?他是如何进行扩容的呢?他是如何实现并发安全呢?等等一系列问题。正是知己知彼才能百战百胜,所以我打算深入理解一下hashMap
hashMap,继承Map集合,以key-value形势存储,其中key可以为null ,value是可以重复,其数据是无序的,且会在扩容的时候发生改变。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
static int indexfor(int h,int length) {
// 其中的legth-1 也是为什么 hashMap的容量为2的n次幂的原因
return h & (length-1);
}
从上面的两种通过hash值计算数组下表位置index的方式都可以将计算出来的值在数组length的长度内。至于那种性能更高速度更快,散列的空间更加均匀,那毋庸置疑,肯定1.8里面的。
public V get(Object key) {
Segment<K,V> s;
HashEntry<K,V>[] tab;
int h = hash(key);
long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null && //获取volatile
(tab = s.table) != null) {
for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile //获取volatile
(tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
e != null; e = e.next) {
K k;
if ((k = e.key) == key || (e.hash == h && key.equals(k)))
return e.value;
}
}
return null;
}
https://blog.csdn.net/qq_36520235/article/details/82417949(强力推荐!上面两个流程图来源) https://www.jianshu.com/p/8cf5af30f245(得补补运算符了) https://www.zhihu.com/question/20733617 (hash算法) https://www.jianshu.com/p/4d3cb99d7580 (hash冲突的解决方案)