源码冲浪之手撕HashMap1.7【待完善】

HashMap简介

HashMap是我们最常用到的集合之一,是java非常典型的数据结构。学习它的源码是非常只有必要的,我们所要了解的并不仅仅是“HashMap不是线程安全的,HashTable是线程安全的,通过synchronized实现的。HashMap取值非常快”等等。
了解hashmap必须要先对hashmap的存储结构有个了解
源码冲浪之手撕HashMap1.7【待完善】
它是属于数组及链表相结合的存储结构。如上图 x轴为数组,y轴为链表。
数组存储方式在内存地址是连续大小固定,一旦分配无法被其他引用占用,查询迅速,时间复杂度O(1),插入删除比较慢,时间复杂度为O(n)。
而链表存储方式则与数组相反,属于非连续性,大小非固定,插入及删除块,查询速度慢。
所以HashMap相对中庸。

HashMap的一些常见问题

HashMap的数据结构是啥?数据结构上存储的数据对象结构是啥?

HashMap是一个存储数据对象<封装了K,V属性的对象>的集合,而这个集合是数组+链表类型的数据结构。

根据源码来分析hashMap内部的精髓 hash算法如何保证散列均匀冲突的解决方式?

谈到hash
通常我们jdk的equals在比较的时候就会使用hash算法,此算法会定位到对象的存储位置
具体hash的原理是:
hash函数:找到存储过程
被重写的hashCode(key)
index=h=Hash(int hashCode)
(key.hashCode)&&length -1
length 2^n
通过h就可以找到数组下标的位置
例子如下:
2^4=16
length-1 =15 二进制为 01111
h返回的是 10101
数组上存储的位置为: 00101 【上下都是1才是1】
好处:
1 )散列的范围被低位限制—》散列位置一定在我们的索引范围(即length-1)之内。
2 )低位的0如果越多 代表我们散列的结果越固定。【想象一个若是非length-1就会发生
10000 低位0较多,导致散列结果几乎就是一致】,导致冲突越多,导致数组位置的利用率不高。

HashMap并发闭环问题?

扩容方法会新建一个数组,复制原数组到新的数组,由于下标挂着链表,扩容之后会导致环形链表的出现,JDK1.8已经解决了这个问题了。

手撕HashMap