- 1.哈希函数
关键字和它在表中存储位置之间存在一种函数关系。这个函数我们称为为哈希函数。
key <--(函数关系)--> value
hash:散列、杂凑
就是把任意长度的输入,通过散列算法,变成固定长度的输出,这种是一种压缩映射.
当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。
键(key)经过hash函数得到的结果作为地址去存放当前的键值对(key-value)(hashmap的存值方式),但是却发现该地址已经有值了,就会产生冲突。这个冲突就是hash冲突了。
换句话说就是:如果两个不同对象的hashCode相同,这种现象称为hash冲突。
- 2.HashMap的底层实现
JDK1.8之前:
1)HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。
2)HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
3)扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的hashCode() 方法,换句话说使用扰动函数之后可以减少碰撞。
4)“拉链法” 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
JDK1.8之后:
当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
这几篇博客讲得很详细:
https://blog.csdn.net/qq_41345773/article/details/92066554