那我们来看一下源码是怎样实现的
public static void main(String[] args) {
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("aaaaa", 10);
}
Ctrl + B 快捷键跳转
先计算key 的 hash 值
hash(key)
hash 本质是个数组,为了把元素存进去,就需要把key 值转成数组下标。我们再看源码中是如何计算的。
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
key与其高16位异或,这样计算目的是为了让最后得到的hash值更加分散,冲突概率降低。在这里hashCode 是Object 类自己的方法,任何一个对象都有这样的方法,也可以重写该方法来实现自己的计算规则。
简单介绍一下哈希表&哈希冲突
①哈希表是基于数组的一种存储方式.它主要由哈希函数和数组构成。当要存储一个数据的时候,首先用一个函数计算数据的地址,然后再将数据存进指定地址位置的数组里面。这个函数就是哈希函数,而这个数组就是哈希表。
②哈希冲突是指哈希函数算出来的地址被别的元素占用了,也就是,这个位置有人了。好的哈希函数会尽量避免哈希冲突。
初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
table 是hash 表中的数组,我们再往里看一下
可以看到是Node实现的,再往里看
在这里Node是链表节点,是处理hash 冲突的一种方式。
链地址法:这种方法的是将所有哈希地址相同的元素i构成一个单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在单链表中进行。链地址法适用于经常进行插入和删除的情况。
n = (tab = resize()).length;
resize()就是一个扩容操作,将数组长度变长,始终是2^n,看看resize源码如下:
<< 1就相当于 *2.
根据hash 值找到数组下标,并且把新元素构造成节点插入
三种情况:
a)链表为空
b)链表不为空
c)变成红黑树
///1、链表为空
if ((p = tab[i = (n - 1) & hash]) == null)
// 因为数组产度是2^N , (n - 1) & hash等价于hash%n
// 将元素直接插进去
tab[i] = newNode(hash, key, value, null);
else {
//这时就需要链表或红黑树了
// e是用来查看是不是待插入的元素已经有了,有就替换
Node<K,V> e; K k;
// p是存储在当前位置的元素
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p; //要插入的元素就是p,这说明目的是修改值
// 3、变成红黑树,p是一个树节点
else if (p instanceof TreeNode)
// 把节点添加到树中
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
// 2、链表不为空,这时候就是链表结构了,要把待插入元素挂在链尾
for (int binCount = 0; ; ++binCount) {
//向后循环
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
// 链表比较长,需要树化,
// 由于初始即为p.next,所以当插入第8个元素才会树化
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
// 找到了对应元素,就可以停止了
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
// 继续向后
p = e;
}
扩容
针对数组进行扩容,数组越小hash冲突就越严重,效率就越低,进行扩容就很好的提高效率,这里阈值计算的方式和负载因子密切相关。
就得这张流图很不错就参考过来来源:https://blog.csdn.net/the_one_and_only/article/details/81665098?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159647169419724835817190%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159647169419724835817190&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v25-2-81665098.first_rank_v2_rank_v25&utm_term=hashmap%E7%9A%84put%E5%8E%9F%E7%90%86&spm=1018.2118.3001.4187