HashMap插入操作:
HashMap<String, Integer> map = new HashMap<>();
map.put("hello", 1);
map 是一个集合,集合中保存了 Key-Value 关联的一组元素
1.put做了什么?
如果map中原来有 "hello" 这个 Key 对应的元素
- YES - 把元素中的 value 替换为1,并返回原来的value
- No - 新建一个 "hello"-1 的 key-vlaue 键值对,放入集合中,并且返回 null
2.具体怎么做
JDK中怎么做(理论 + Java做法)
(1)哈希表的理论,根据哈希函数,计算出 key 的值
int h = "hello".hashCode();
(2)把哈希值转化为数组的一个合法下标[0, table.length)
int m = (h >> 16) ^ (h);
int i = (table.length - 1) & m;
(3)判断是否哈希冲突,根据不同的解决冲突的方法(开放地址法、链地址法、再哈希法、建立公共溢出区),确定该组 key-value 元素应该处的位置
通过链表管理冲突元素
利用遍历查找,在 table[i] 对应的链表中找到,key-value 元素所应该在的位置
(4)为了让冲突率保持在一个较低的程度,通过维护负载因子来保证
3.时间复杂度为什么是O(1)
(1)计算哈希值,和集合中的元素个数无关
(2)哈希值变为合法下标
(3)冲突解决(固定长度的链表查找)
如果遇到扩容了,时间复杂度就稍微复杂点
哈希桶中的链表转红黑树
链表 -> 红黑树 前提条件:链表中的元素超过了一个阙值(本质上是出现了剧烈的哈希冲突)
- 在哈希函数良好的情况下(得到的哈希值符合均匀分布)
- 每个下标中,落入多少元素的概率符合泊松分布
- 超过这个阙值的概率:千万分之一以上