HashMap存在的意义(数组与链表的区别)

今天被面试问到HashMap的由来,即为什么要有这种数据结构,单纯的数组查询效率不是很高吗?我没答上来,之后搜了下,原来要从数组和链表数据结构的优缺点来答,具体如下:

首先当我们需要存储数据的时候,动态数组虽然能够自动扩容,但是必须在初始时刻指定初始容量。而对于那些在编译时无法确定具体的数量即动态增长的数据,就需要用到Java集合类了。对于ArrayList 和 LinkedList,还有 Vector它们都有一些缺点,要么插入删除速度慢、要么就是遍历速度慢。那么有没有一种插入、删除、遍历都比较不错的集合类呢?于是 HashMap 就出现了。HashMap 是一个散列表,它存储的是一组键值对(key-value)的集合,并实现快速的查找。

(1)为了实现快速查找,HashMap 选择了数组而不是链表。以利用数组的索引实现 O(1) 复杂度的查找效率。

(2)为了利用索引查找,HashMap 引入 Hash 算法, 将 key 映射成数组下标: key -> Index。

(3)引入 Hash 算法又导致了 Hash 冲突。为了解决 Hash 冲突,HashMap 采用链地址法,在冲突位置转为使用链表存储。

(4)链表存储过多的节点又导致了在链表上节点的查找性能的恶化。为了优化查找性能,HashMap 在链表长度超过 8 之后转而将链表转变成红黑树,以将 O(n) 复杂度的查找效率提升至 O(log n)。

综上

HashMap 存在的意义就是实现一种快速的查找并且插入、删除性能都不错的一种 K/V(key/value)数据结构。

下面具体来看下数组和链表的差别:

数组(Array)

一、数组特点:

所谓数组,就是相同数据类型的元素按一定顺序排列的集合;数组的存储区间是连续的,占用内存比较大,故空间复杂的很大。但数组的二分查找时间复杂度小,都是O(1);数组的特点是:查询简单,增加和删除困难;

1.1 在内存中,数组是一块连续的区域

1.2 数组需要预留空间

  在使用前需要提前申请所占内存的大小,如果提前不知道需要的空间大小时,预先申请就可能会浪费内存空间,即数组的空间利用率较低。注:数组的空间在编译阶段就需要进行确定,所以需要提前给出数组空间的大小(在运行阶段是不允许改变的)

1.3 在数组起始位置处,插入数据和删除数据效率低。

插入数据时,待插入位置的元素和他后面的所有元素都需要向后搬移

删除数据时,待删除位置后面的所有元素都需要向前搬移。

1.4 随机访问效率很高,时间复杂度可以达到O(1)

因为数组的内存是连续的,想要访问那个元素,直接从数组的首地址向后偏移就可以访问到了。

1.5 数组开辟的空间,在不够使用的时候需要进行扩容;扩容的话,就涉及到需要把旧数组中的所有元素向新数组中搬移。

1.6 数组的空间是从栈分配的。(栈:先进后出)

二、数组的优点:

随机访问性强,查找速度快,时间复杂度是0(1)

三、数组的缺点:

3.1 从头部删除、从头部插入的效率低,时间复杂度是o(n),因为需要相应的向前搬移和向后搬移。

3.2 空间利用率不高

3.3 内存空间要求高,必须要有足够的连续的内存空间。

3.4 数组的空间大小是固定的,不能进行动态扩展。

链表(ListNode)

一、链表的特点:

所谓链表,链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

链表:链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:查询相对于数组困难,增加和删除容易。

1.1 在内存中,元素的空间可以在任意地方,空间是分散的,不需要连续。

1.2 链表中的元素有两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址。

   每一个数据都会保存下一个数据的内存地址,通过该地址就可以找到下一个数据

1.3 查找数据时间效率低,时间复杂度是o(n)

 因为链表的空间是分散的,所以不具有随机访问性,如果需要访问某个位置的数据,需要从第一个数开始找起,依次往后遍历,知道找到待查询的位置,故可能在查找某个元素时,时间复杂度是o(n)

1.4 空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高

1.5 任意位置插入元素和删除元素时间效率较高,时间复杂度是o(1)

1.6 链表的空间是从堆中分配的。(堆:先进先出,后进后出)

二、链表的优点

2.1 任意位置插入元素和删除元素的速度快,时间复杂度是o(1)

2.2 内存利用率高,不会浪费内存

2.3 链表的空间大小不固定,可以动态拓展。

三、链表的缺点

随机访问效率低,时间复杂度是o(1)

总之:

对于想要快速访问数据,不经常有插入和删除元素的时候,选择数组;

对于需要经常的插入和删除元素,而对访问元素时的效率没有很高要求的话,选择链表。

那么HashMap就是结合了两者的特点,既有数组查找效率快的优势,又有链表插入和删除元素速度快的特点,并且有动态扩展机制。

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值