插入删除,链表真的比数组快嘛?

本文通过实验比较了ArrayList与LinkedList在进行随机删除操作时的性能表现。结果显示,在100万个元素中随机删除1万个元素时,ArrayList的性能优于LinkedList。文章还分析了可能的原因:一方面,数组复制为本地方法;另一方面,连续内存复制速度快于寻址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天看到吧友发了个帖子,叫 想编写优美的java代码格式要记住这几条规则
其中有一条,叫做
ArrayList底层是使用数组实现的,因此随机读取数据会比LinkedList快很多,而LinkedList是使用链表实现的,新增和删除数据的速度比ArrayList快不少。


这句话当然木有问题啦,在提出帖子标题的时候,楼主也想骂自己是逗比。不过想想,似乎在日常写代码的时候,伴随“新增和删除”之前的操作,往往是“随机访问”(如果是因为我代码量少产生的错觉,各位大牛勿喷)


既然这样,那么LinkedList真比ArrayList快嘛?


换句话说,
随机访问+数组元素复制 VS 寻址+插入删除 哪个更快?
忽略掉那一个元素,也就是元素的复制和寻址,哪个更快?

package test2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;

public class Array_link {

	public static void main(String[] args)
	{
		long arrListTime = 0 ;
		long linkListTime = 0 ;
		Integer[] ia1 = new Integer[1000000];
		for(int i= 0;i<1000000;i++)
		{
			ia1[i] = i;
		}
		
		Random random = new Random();
		ArrayList array = new ArrayList<Integer>(Arrays.asList(ia1));
		LinkedList link = new LinkedList<Integer>(Arrays.asList(ia1));
		
		
		for(int i=0;i<10000;i++)
		{
			int r = random.nextInt(array.size());
			
			long arrTime = System.currentTimeMillis();
			array.remove(r);
			arrListTime =arrListTime + System.currentTimeMillis() - arrTime;
			
			long linkTime = System.currentTimeMillis();
			link.remove(r);
			linkListTime =linkListTime + System.currentTimeMillis() - linkTime;
			
		}
		
	
		System.out.println("ArrayList time-consuming:"+ arrListTime);
		System.out.println("LinkedList time-consuming:"+ linkListTime);
	}
}

结果为
ArrayList time-consuming:9280
LinkedList time-consuming:40693

100W个数字里随机删除1W个数字,数组更快

1.一方面是arraycopy为本地的方法,另一方面相邻连续内存的复制要比寻址快
2.当单个元素的数据量增大,数组将显著变慢
### 数组链表性能对比 数组链表作为两种常见的线性数据结构,在不同的应用场景下各有优劣。以下是它们之间的主要区别及其原因分析: #### 查询性能 数组支持随机访问,这意味着可以通过索引直接定位到目标元素的位置[^3]。由于数组中的元素在内存中是连续存储的,这种特性使得现代计算机的 CPU 缓存能够高效地预取相邻的数据块[^2]。因此,即使理论上数组链表的查询时间复杂度均为 O(n),实际运行时数组的查询速度远超链表。 相比之下,链表的节点分布在堆空间的不同位置,无法利用 CPU 的缓存机制。每次访问都需要通过指针逐一跳转至下一个节点,这导致其查询效率显著降低。 #### 插入删除操作 尽管数组在查询方面具有优势,但在插入删除操作上表现较差。对于动态调整大小的需求,数组需要复制整个数据集到新的地址并更新引用关系,这一过程的时间复杂度为 O(n)。然而,如果仅考虑静态环境下的简单增删动作,则开销相对较小。 链表则擅长频繁发生的插入删除任务,特别是靠近两端的操作几乎无需额外成本即可完成。这是因为只需改变局部几个结点间的连接状态而不必挪动其他成员[^1]。 #### 存储布局影响 从底层实现角度来看,数组占用一段固定的连续区域用于保存同质化的项目集合;而链表由多个独立分配的小单元构成——每个都包含有效载荷加上至少一个指向邻居对象的链接字段。这样的设计决定了前者更容易满足硬件层面优化条件(如上述提及的cache locality),后者却难以享受此类红利. ```python # 示例代码展示如何定义简单的数组链表结构 class Node: def __init__(self, value=None, next_node=None): self.value = value self.next = next_node def create_linked_list(values): head = None prev = None for v in values[::-1]: node = Node(v, head) if not head: head = node else: prev.next = node prev = node return head arr_example = [i * i for i in range(10)] # 创建一个平方数列组成的数组实例 llist_head = create_linked_list([j*j for j in range(5)]) # 构建类似的链表示例 ``` 综上所述,数组之所以通常比链表主要是得益于它优秀的本地性和速寻址能力所带来的综合效益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值