一,HashMap概述
简单来说,HashMap的实现是"数组+链表",数组是HashMap的主体,链表则是主要为了解决哈希冲突而设立的。
- 数组的优缺点:采用一段连续的存储单元来存储数据的,对于下标查找,它的时间复杂度为O(1);而对于删除,修改操作,涉及到数组元素的移动,其平均的时间复杂度为O(N)
- 链表的优缺点:在链表中查找一个元素的话,需要以遍历链表的方式去查找,时间复杂度为O(n);而对于删除,修改操作,仅需要处理节点间的引用,时间复杂度为O(1);
对于查找来说,数组更加的方便;对于删除,修改,链表更加的方便。
hash表的概述
hash表的本质就是一个数组,数组中的每一个元素被称为一个箱子(bin),箱子中存放的是键值对。
存储过程如下:
- 根据k值计算他的哈希值h.
- 假设箱子的个数为n,那么键值对就放在第(h%n)这个箱子中。
- 如果这个箱子中已经有键值对,就使用开放寻址法或者拉链法(每个箱子其实是一个链表,属于同一个箱子的所有键值对都会排列在链表中)解决冲突。
hash表进行增删改操作时,性能十分之高,不考虑hash冲突的影响下,仅需一次定位即可,时间复杂度为O(1).
HashMap由Entry数组+链表组成,如下图所示:
从上图我们可以发现HashMap是由Entry数组+链表
组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len
获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108
以及140都存储在数组下标为12
的位置。
负载因子,是用来衡量哈希表的空/满程度,负载因子=总键值对/箱子个数。负载因子越大,意味着哈希表越满,越容易导致冲突,性能也就越低。