1.什么是HashMap
Hash: 散列将一个任意的长度通过某种(hash函数)算法转换成一个固定值
Map: 地图, (x,y)存储
底层就是一个数组结构, 数组中的每一项又是一个链表, 当新建一个HashMap的时候, 就会初始化一个数组
总结: 通过 hash 出来值, 然后通过值定位到某个 map, 然后value 存储到这个 map中, value只不过是 key 的附属.
2.源码分析
先给出结论
数据结构:
- 底层是数组
Entry
就是数组中的元素- 每个
Map.Entry
其实就是一个key-value
对, 它持有一个指向下一个元素的引用Entry<K,V> next;
, 这就构成了链表
存取实现:
- 存储
put
:- 过程
- 先根据
key
的hashCode
重新计算hash
值, 根据hash
值得到这个元素在数组中的位置(下标) - 如果数组该位置上已经存放有其他元素了, 那么在这个位置上的元素将以链表的形式存放, 新加入的放在链头, 最先加入的放在链尾.
- 如果数组该位置上没有元素, 就直接将该元素放到数组中的该位置上.
- 先根据
- 注意点
- 当系统决定存储
HashMap
中的key-value
对时,完全没有考虑Entry
中的value
,仅仅只是根据key
来计算并决定每个Entry
的存储位置。当系统决定了key
的存储位置之后,value
随之保存在那里即可。 - 对于于任意给定的对象,只要它的
hashCode()
返回值相同,那么程序调用hash(int h)
方法所计算得到的hash
码值总是相同的。 - 本质上就是把
hash
值对数组长度取模运算, 这样一来,元素的分布相对来说是比较均匀的 - 但是系统是用的位运算, 方法更巧妙, 消耗更小
- 当系统决定存储
- 过程
- 读取
get
- 过程
- 首先计算
key
的hashCode
,找到数组中对应位置的某一元素,然后通过key
的equals
方法在对应位置的链表中找到需要的元素。
- 首先计算
- 过程
存储实现总结:
HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。
HashMap 底层采用一个 Entry[] 数组来保存所有的 key- value 对,当需要存储一个 Entry 对象时,会根据 hash 算法来决定其在数组中的存储位置,在根据 equals 方法决定其在该数组位置上的链表中的存储位置;
- 当需要取出一个 Entry 时,也会根据 hash 算法找到其在数组中的存储位置,再根据 equals 方法从该位置上的链表中取出该 Entry。
3. HashMap 的性能参数
1 | /** |