Java数组与链表的区别

本文对比了数组和链表在存储结构、查询效率、内存分配和频繁操作方面的优缺点。数组适合数据查找为主且长度固定,利用程序局部性提升性能;链表在大空间分配和频繁插入删除时更高效,但查询效率较低。
摘要由CSDN通过智能技术生成

一、存储结构不同

数组是物理存储单元上连续、顺序的存储结构,它的每个元素在内存中都是连续紧邻分配的,它所占用的内存空间取决于初始化的长度,一旦创建了一个数组,它的长度就不可改变。

而链表与数组正相反,链表是物理存储单元上非连续非顺序的存储结构,它是由一个个结点,通过指针联系起来的,其中每个结点包括数据和指针。使用链表时,不需要指定长度,它的长度是可变的。

二、适用情景不同

先说结论:如果数据以查为主,很少涉及到增和删,选择数组,如果数据涉及到频繁的插入和删除,或元素所需分配空间过大,倾向于选择链表。

数组适用情景

数组的查询效率普遍是高于链表的。数组提供元素下标来访问元素,如果我们知道要查找的元素的下标,我们可以直接通过下标来获取元素,时间复杂度是O(1)。而很多情况下我们并不知道元素下标,还可以根据数组是否有序,选择合适的查找方法进行查找。即使是最坏的情况,使用线性查找在无序数组中查询元素,由于其存储在一块连续的内存空间中,CPU在进行查找时,效率也会比链表快。因为链表的存储结构是不连续的,查询任意一个元素都需要从头结点开始遍历,数据相同的情况下,查询效率自然会慢一点。 

数组的查询效率高于链表还有一个原因,那就是程序局部性原理。什么是程序局部性原理?

程序局部性原理

众所周知,CPU的运行速度是非常快的,如果CPU每次运算都要到内存中去取数据无疑是很耗时的,所以在CPU和内存之间往往集成了很多层级的缓存,这些缓存越接近CPU,速度越快,所以如果能提前把内存中的数据加载到各级缓存中,那么下次CPU取数的话直接从这些缓存里取即可,能加快CPU执行速度。

那什么情况下内存中的数据会被提前加载到缓存中呢?答案是当某个元素被用到的时候,那么这个元素地址附近的元素会被提前加载到缓存中。

举个例子,现创建一个整形数组,里面存储1,2,3,4四个整数,当程序用到了数组中的某个元素时(比如1),由于CPU认为既然1被用到了,那么紧邻它的元素2,3,4被用到的概率就很大,所以会提前把2,3,4加载到缓存中,这样CPU再次执行的时候如果用到了2,3,4,直接从缓存里取就行了,能提升不少性能。

而对于链表来说,由于链表的每个结点在内存中都是随机分布的,只是通过指针联系在一起,所以这些结点的地址并不相邻,自然无法利用程序局部性原理来提前加载到缓存中来提升性能了。

链表使用情景

相比数组,链表的非连续,非顺序让它在查询性能上处于劣势,但它在其他情况下性能很高。

大空间内存分配

由于数组空间的连续性,如果要为数组分配500M的空间,这500M的空间必须是连续的,未使用的,所以在内存空间的分配上数组的要求会比较严格,如果内存碎片太多,分配连续的大空间很可能导致失败。而链表由于是非连续的,所以这种情况下选择链表更合适。

元素频繁删除和插入

如果涉及到元素的频繁删除和插入,用链表就会高效很多,对于数组来说,如果要在元素间插入一个元素,需要把其余元素一个个往后移,以为新元素腾空间(同理,如果是删除则需要把被删除元素之后的元素一个个往前移),效率上无疑是比较低的。而链表的插入删除相对来说就比较简单了,修改指针位置即可,其他元素无需做任何移动操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值