当前位置: 首页 > news >正文

ArrayList 和LinkedList的区别比较

前言

‌ArrayList和LinkedList的主要区别在于它们的底层数据结构、性能特点以及适用场景。‌ArrayList和LinkedList从名字分析,他们一个是Array(动态数组)的数据结构,一个是Linked(链表)的数据结构,此外,他们两个都是对List接口的实现。前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列。

一、底层数据结构

ArrayList‌:基于动态数组实现。它维护一个Object类型的数组来存储元素,可以根据需要自动扩展容量。当元素数量超过当前容量时,ArrayList会进行扩容操作,通常是将现有元素复制到一个新的更大数组中‌。 

LinkedList‌:基于双向链表实现。每个节点包含存储的元素、指向前一个节点的引用和指向下一个节点的引用。LinkedList不需要预先分配固定大小的空间,可以在链表的头部或尾部灵活地添加或删除元素‌。

二、性能特点

2‌.1 查询性能‌:

ArrayList‌:通过索引直接访问元素,查询速度非常快,时间复杂度为O(1)。适合需要频繁访问特定‌位置数据的场景‌。

LinkedList‌:由于需要遍历链表来找到指定索引的元素,查询速度较慢,时间复杂度为O(n)‌。

2.2 添加和删除性能‌:

‌ArrayList‌:在列表中间插入或删除元素时,需要移动后续的所有元素,时间复杂度为O(n)。因此,在列表中间进行添加或删除操作时,LinkedList通常更快‌。

LinkedList‌:在头部或尾部添加或删除元素时,只需更改指针引用,时间复杂度为O(1),因此在这些位置进行操作时更快‌。

三、空间和耗时效率对比

从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的变化,但是他的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的数据量的变化而变化,但是他不便于使用。

ArrayList主要的空间开销在于需要在IList列表预留一定空间;而LinkedList主要空间开销在于需要存储节点信息以及结点指针信息。

ArrayList想要在指定位置插入或删除元素时,主要耗时的是 System.arraycopy 动作,会移动 index 后面所有的元素;LinkedList 主耗时的是要先通过 for 循环找到 index,然后直接插入或删除。这就导致了两者并非一定谁快谁慢。 主要有两个因素决定他们的效率,插入的数据量和插入的位置。

LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。

四、ArrayList 扩容问题

ArrayList 使用一个内置的数组来存储元素,这个数组的起始容量是 10,当数组需要增长时,新的容量按如下公式获得:新容量=(旧容量*3)/2+1,也就是说每一次容量大概会增长50%。这就意味着,如果你有一个包含大量元素的 ArrayList 对象,那么最终将有很大的空间会被浪费掉,这个浪费是由ArrayList的工作方式本身造成的。如果没有足够的空间来存放新的元素,数组将不得不被重新进行分配以便能够增加新的元素。对数组进行重新分配,将会导致性能急剧下降。

五、ArrayList随机访问比LinkedList快的原因

ArrayList从原理上就是数据结构中的数组,也就是内存中的一片空间,这意味着,当我get(index)的时候,我可以根据数组的首地址+偏移量,直接计算出我想访问的第index元素在内存中的位置;而LinkedList可以简单理解为数据结构中的链表,在内存中开辟的不是一段连续的空间,而是每个元素有一个元素和下一个元素地址这样的内存结构,当get(index)时,只能从首元素开始,依次获取下一个元素的地址。上面已经说过,用时间复杂度来表示的话,ArrayList的get(index)是O(1),而LinkedList是O(n)。

我们编写代码对比测试,说明两者的性能:

1. 定义抽象类,作为List接口的测试,并定义有测试方法

//定义内部抽象类,作为List测试。
private abstract static class Tester {String name;int size;Tester(String name, int size) {this.name = name;this.size = size;}//定义抽象方法abstract void test(List a);}

2. 定义一个测试的数组,分别存储获取、遍历、插入和删除的方法

private static final int LOOP_COUNTS = 1000;private static Tester[] tests = {//一个测试数组,存储get(随机取)、iteration(顺序遍历)、insert(中间插入)、remove(随机删除)new Tester("get", 500) {void test(List a) {for (int i = 0; i < LOOP_COUNTS; i++) {for (int j = 0; j < a.size(); j++) {a.get(j);}}}},new Tester("iteration", 500) {void test(List a) {for (int i = 0; i < LOOP_COUNTS; i++) {Iterator it = a.iterator();while (it.hasNext()) {it.next();}}}},new Tester("insert", 2000) {void test(List a) {int half = a.size() / 2;String s = "test";ListIterator it = a.listIterator(half);for (int i = 0; i < size * 10; i++) {it.add(s);}}},new Tester("remove", 5000) {void test(List a) {ListIterator it = a.listIterator(3);while (it.hasNext()) {it.next();it.remove();}}}};

 3. 编写测试方法

public static void test(List a) {//输出测试的类名称System.out.println("Testing for --" + a.getClass().getName());for (int i = 0; i < tests.length; i++) {fill(a, tests[i].size);//填充空集合System.out.print(tests[i].name);long t1 = System.currentTimeMillis();tests[i].test(a);//进行测试long t2 = System.currentTimeMillis();System.out.print("花费时间:" + (t2 - t1) + " ms ,");}}public static Collection fill(Collection c, int size) {for (int i = 0; i < size; i++) {c.add(Integer.toString(i));}return c;}

4. 调用ArrayList和LinkedList的方法

public static void main(String[] args) {test(new ArrayList());System.out.println();test(new LinkedList());}

 5. 运行结果

六、适用场景

‌ArrayList‌:适合需要频繁访问特定位置数据的场景,如排行榜、购物车列表等。由于扩容机制的存在,建议在创建时指定初始容量以减少扩容次数‌。

‌LinkedList‌:适合需要频繁在列表开头、中间或末尾进行添加和删除操作的场景。由于其链表结构,插入和删除操作更为高效‌。

总之, 它们的适用场景:Array数组,查找快,插入删除慢。 适用于频繁查找和修改的场景。Linked链表,插入删除快,查找修改慢。适用于频繁添加和删除的场景。

相关文章:

ArrayList 和LinkedList的区别比较

前言 ‌ArrayList和LinkedList的主要区别在于它们的底层数据结构、性能特点以及适用场景。‌ArrayList和LinkedList从名字分析&#xff0c;他们一个是Array&#xff08;动态数组&#xff09;的数据结构&#xff0c;一个是Linked&#xff08;链表&#xff09;的数据结构&#x…...

Wallpaper壁纸制作学习记录13

骨骼物理模拟 Wallpaper Engine还允许您为人偶变形骨骼配置某些物理模拟。选择骨骼时&#xff0c;点击编辑约束来配置骨骼这些属性。 警告 请记住&#xff0c;物理模拟可能会根据用户的最大FPS设置略微改变其行为。 Wallpaper Engine编辑器将始终以高帧速率渲染。您可以将壁纸…...

Visual Studio 2022安装教程

1、下载网址 Visual Studio 2022 IDE安装网址借助 Visual Studio 设计&#xff0c;具有自动完成、构建、调试、测试功能的代码将与 Git 管理和云部署融为一体。https://visualstudio.microsoft.com/zh-hans/vs/ 点击图片所示 双击运行 2、安装 点击C桌面开发&#xff08;右边…...

std__invoke 的使用

std__invoke 的使用 文章目录 std__invoke 的使用1. std::invoke 的功能2. 语法3. 使用场景1. 调用普通函数2. 调用成员函数3. 调用成员函数&#xff08;通过指针或引用&#xff09;4. 调用函数对象&#xff08;仿函数&#xff09;5. 调用 Lambda 表达式 4. std::invoke 的优势…...

2501d,d.109

原文 2.109.0带来了15个主要更改和26个修复的Bugzilla问题.非常感谢39位贡献者,是他们使2.109.0变成可能. 更改编译器 1,[下一版]现在,为类型实例的成员设置别名是个错误 2,添加位字段内省功能 3,添加了从CTFE写入消息的__ctfeWrite 4,现在-verrors也限制弃用警告 5,dtoh为e…...

1、蓝牙打印机环境搭建

本项目采用stm32f103c8T6芯片&#xff0c;通过库函数实现打印功能&#xff0c;并配置有小程序蓝牙通信上位机。 1、创建文件夹目录 core文件夹存放核心库文件 LIB文件夹存放标准库函数文件 这里可以删减&#xff0c;用不到的可以不要。 obj存放编译后的文件 project存放项目…...

Axure RP11安装学习

安装&#xff1a; 官网下载地址&#xff1a;Axure RP - UX Prototypes, Specifications, and Diagrams in One Tool 设置自己的安装目录&#xff0c;一步步安装即可。 汉化&#xff1a; 汉化包下载地址&#xff1a; 链接: https://pan.baidu.com/s/1eIRoGkVqAY3u3I27lgDJ6A…...

axios和fetch的实现原理以及区别,与XMLHttpRequest的关系,并结合react封装统一请求示例

Axios 和 Fetch 对比及统一请求封装 1. Axios 基础用法 1.1 安装和引入 // 安装 npm install axios// 引入 import axios from axios;1.2 基本请求方法 // GET 请求 axios.get(/api/users).then(response > console.log(response.data)).catch(error > console.error…...

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…...

C++软件设计模式之模板方法模式

模板方法模式是面向对象软件设计模式之一&#xff0c;其主要意图是在一个方法中定义一个算法的骨架&#xff0c;而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。 动机 在软件开发中&#xff0c;常常会遇到这样的情…...

神经网络的初始化方式都有哪些?

一、概念 神经网络的初始化是深度学习中的一个关键步骤&#xff0c;它指的是在训练开始前为神经网络的权重和偏置设置初始值。合适的初始化方法可以加速模型的收敛&#xff0c;提高训练效果&#xff0c;甚至影响模型的最终性能。当然&#xff0c;目前我们使用Torch、TensorFlow…...

const成员函数

在c中经常看到这样的声明&#xff1a; class A{ ... int fun1() const; //const成员函数 int fun2() const; //const成员函数private: int a; //属于状态 static int b; //不属于状态&#xff0c;属于类 } 这个const关键字声明了这个函数是const成员函数&#xff0c;con…...

物理知识1——电流

说起电流&#xff0c;应该从电荷说起&#xff0c;而说起电荷&#xff0c;应该从原子说起。 1 原子及其结构 常见的物质是由分子构成的&#xff0c;而分子又是由原子构成的&#xff0c;有的分子是由多个原子构成&#xff0c;有的分子只由一个原子构成。而原子的构成如图1所示。…...

车载通信架构 --- 智能汽车通信前沿技术

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

Flutter中添加全局防护水印的实现

随着版权意识的加强&#xff0c;越来越多的应用开始在应用内部增加各种各样的水印信息&#xff0c;防止核心信息泄露&#xff0c;便于朔源。 效果如下&#xff1a; 在Flutter中增加全局水印的方式&#xff0c;目前有两种实现。 方案一&#xff0c;在native层添加一个遮罩层&a…...

BGP(Border Gateway Protocol)路由收集器

全球 BGP&#xff08;边界网关协议&#xff09;路由收集器的分布情况以及相关数据。以下是主要的信息解读&#xff1a; 地图标记&#xff1a; 每个绿色点代表一个路由收集器的位置。路由收集器分布在全球不同的地区&#xff0c;覆盖了五大区域&#xff1a; ARIN&#xff08;美…...

【DAGMM】直接跑tip

1.from sklearn.externals import joblib 版本高 joblib没有 直接pip install joblib&#xff0c;然后 import joblib 2.AttributeError: module ‘tensorflow’ has no attribute ‘set_random_seed’ # tf.set_random_seed(args.seed)#tf<2.0 tf.random.set_seed(args.s…...

vscode中调用deepseek实现AI辅助编程

来自 Python大数据分析 费弗里 1 简介 大家好我是费老师&#xff0c;最近国产大模型Deepseek v3新版本凭借其优秀的模型推理能力&#xff0c;讨论度非常之高&#x1f525;&#xff0c;且其官网提供的相关大模型API接口服务价格一直走的“价格屠夫”路线&#xff0c;性价比很高…...

AI大模型语音识别转文字

提取音频 本项目作用在于将常见的会议录音文件、各种语种音频文件进行转录成相应的文字&#xff0c;也可从特定视频中提取对应音频进行转录成文字保存在本地。最原始的从所给网址下载对应视频和音频进行处理。下载ffmpeg(https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-…...

可由 (5V) 单片机直接驱动的模块

可由 &#xff08;5V&#xff09; 单片机 直接驱动的模块 1. 传感器类 元器件描述温度传感器DS18B20&#xff08;数字温度传感器&#xff09;光强传感器光敏电阻&#xff08;通过 ADC 读取&#xff09;红外传感器红外接收模块&#xff08;如 VS1838&#xff09;超声波传感器HC…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?

在现代前端开发中&#xff0c;Utility-First (功能优先) CSS 框架已经成为主流。其中&#xff0c;Tailwind CSS 无疑是市场的领导者和标杆。然而&#xff0c;一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...