参考下面的文章:
hashmap的底层实现
下面是我的简单总结,想看详细的请看上面的文章:
1.hashmap不是线程安全的,不可以用在多线程上
2.hashmap的底层实现是数组和链表,数组用来存储键和值,链表用来解决hash冲突
3.HashMap 包含如下几个构造器:
(1)HashMap():构建一个初始容量为 16,负载因子为 0.75 的HashMap。
(2)HashMap(int initialCapacity):构建一个初始容量为 initialCapacity,负载因子为 0.75 的 HashMap。
(3)HashMap(int initialCapacity, float loadFactor):以指定初始容量、指定的负载因子创建一个 HashMap。
HashMap的基础构造器HashMap(int initialCapacity, float loadFactor)带有两个参数,它们是初始容量initialCapacity和加载因子loadFactor。
initialCapacity:HashMap的最大容量,即为底层数组的长度。
loadFactor:负载因子loadFactor定义为:散列表的实际元素数目(n)/ 散列表的容量(m)。
负载因子衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。
HashMap的实现中,通过threshold字段来判断HashMap的最大容量:
threshold = (int)(capacity * loadFactor);
结合负载因子的定义公式可知,threshold就是在此loadFactor和capacity对应下允许的最大元素数目,超过这个数目就重新resize,以降低实际的负载因子。默认的的负载因子0.75是对空间和时间效率的一个平衡选择。当容量超出此最大容量时, resize后的HashMap容量是容量的两倍
4.调用hashmap的get函数时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。
5.调用hashmap的put函数时,首先会检查元素的Key是否为Nul,如果key为null的话,hash值为0,对象存储在数组中索引为0的位置。即table[0].
如果key不为Null,则计算元素的哈希值,并根据哈希值找到元素在数组中的对应的位置,然后比较Key的值,如果Key的值相同,则用新的value覆盖旧的value,如果值不相同,则把元素设置为该位置对应链表的头指针,把旧的键值对放在新元素的后面。