Java_ArrayList与顺序表复习笔记
ArrayList 与顺序表复习笔记1. 学习目标掌握线性表、顺序表、ArrayList 的基本概念、常见操作、遍历方式、扩容机制以及 ArrayList 在实际案例中的使用。2. 线性表2.1 概念线性表是由n个具有相同特性的数据元素组成的有限序列。常见线性表包括顺序表链表栈队列2.2 逻辑结构与物理结构线性表在逻辑上是线性结构即元素之间呈现一条连续的线性关系。但线性表在物理存储上不一定连续常见的物理存储方式有两种数组存储物理地址连续。链式存储物理地址不一定连续通过引用或指针连接元素。3. 顺序表3.1 概念顺序表是使用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般情况下顺序表底层使用数组实现并在数组上完成增、删、查、改等操作。3.2 顺序表的核心特点底层空间连续。支持通过下标随机访问。插入和删除可能需要搬移元素。容量不够时需要扩容。3.3 顺序表基本结构publicclassSeqList{privateint[]array;privateintsize;// 默认构造方法SeqList(){}// 将顺序表的底层容量设置为 initcapacitySeqList(intinitcapacity){}}其中array底层数组用于存储元素。size当前顺序表中的有效元素个数。3.4 顺序表常见接口// 新增元素默认在数组最后新增publicvoidadd(intdata){}// 在 pos 位置新增元素publicvoidadd(intpos,intdata){}// 判断是否包含某个元素publicbooleancontains(inttoFind){returntrue;}// 查找某个元素对应的位置publicintindexOf(inttoFind){return-1;}// 获取 pos 位置的元素publicintget(intpos){return-1;}// 将 pos 位置的元素设置为 valuepublicvoidset(intpos,intvalue){}// 删除第一次出现的关键字 keypublicvoidremove(inttoRemove){}// 获取顺序表长度publicintsize(){return0;}// 清空顺序表publicvoidclear(){}// 打印顺序表通常用于测试publicvoiddisplay(){}3.5 顺序表插入与删除的代价插入元素在指定位置插入元素时需要将该位置及其后面的元素整体向后移动一位。时间复杂度O(N)删除元素删除指定位置元素时需要将该位置后面的元素整体向前移动一位。时间复杂度O(N)4. ArrayList 简介4.1 ArrayList 的本质ArrayList是 Java 集合框架中的一个普通类实现了List接口。它的底层是一段连续空间支持动态扩容本质上是一个动态类型的顺序表。4.2 ArrayList 的主要特点使用泛型实现使用前通常需要实例化并指定元素类型。实现了RandomAccess接口支持随机访问。实现了Cloneable接口支持克隆。实现了Serializable接口支持序列化。底层使用数组存储元素。支持自动扩容。不是线程安全的。4.3 线程安全问题ArrayList适合在单线程环境中使用。多线程环境中可以考虑VectorCopyOnWriteArrayList5. ArrayList 的构造方法构造方法说明ArrayList()无参构造创建空列表ArrayList(int initialCapacity)指定初始容量ArrayList(Collection? extends E c)使用其他集合构造 ArrayList5.1 推荐写法ListIntegerlist1newArrayList();推荐使用接口接收实现类对象便于后续替换实现。5.2 指定初始容量ListIntegerlist2newArrayList(10);当可以预估元素数量时可以指定初始容量减少扩容次数。5.3 使用已有集合构造ArrayListIntegerlist3newArrayList(list2);构造完成后list3中的元素与list2中的元素一致。5.4 避免使用原生类型不推荐这样写Listlist4newArrayList();list4.add(111);list4.add(100);原因省略泛型后集合中可以存放任意类型元素后续使用时容易出现类型转换问题。推荐这样写ListIntegerlistnewArrayList();6. ArrayList 常见操作方法说明boolean add(E e)尾插元素evoid add(int index, E element)将元素插入到index位置boolean addAll(Collection? extends E c)尾插集合c中的所有元素E remove(int index)删除index位置的元素boolean remove(Object o)删除第一次出现的元素oE get(int index)获取index位置的元素E set(int index, E element)将index位置元素修改为elementvoid clear()清空集合boolean contains(Object o)判断元素是否存在int indexOf(Object o)返回元素第一次出现的下标int lastIndexOf(Object o)返回元素最后一次出现的下标ListE subList(int fromIndex, int toIndex)截取[fromIndex, toIndex)范围内的元素6.1 添加元素ListStringlistnewArrayList();list.add(JavaSE);list.add(JavaWeb);list.add(JavaEE);add(E e)默认将元素添加到末尾。6.2 获取元素个数System.out.println(list.size());size()返回集合中有效元素个数。6.3 获取指定位置元素System.out.println(list.get(1));注意下标范围必须是[0, size)否则会抛出下标越界异常。6.4 修改指定位置元素list.set(1,JavaWEB);set会覆盖指定下标位置上的原元素。6.5 指定位置插入元素list.add(1,Java数据结构);插入后原来index位置及其后面的元素会统一向后移动。6.6 删除指定元素list.remove(JVM);删除第一次出现的指定元素删除成功后其后面的元素会统一向前移动。6.7 删除指定下标元素list.remove(list.size()-1);注意下标不能超过有效元素范围否则会抛出下标越界异常。6.8 判断元素是否存在if(list.contains(测试课程)){list.add(测试课程);}contains返回true表示集合中存在指定元素否则返回false。6.9 查找元素位置list.add(JavaSE);System.out.println(list.indexOf(JavaSE));System.out.println(list.lastIndexOf(JavaSE));indexOf从前往后查找返回第一次出现的位置。lastIndexOf从后往前查找返回最后一次出现的位置。6.10 截取子列表ListStringretlist.subList(0,4);subList(0, 4)表示截取[0, 4)范围内的元素。注意subList返回的子列表与原列表存在关联修改时要特别小心。6.11 清空集合list.clear();System.out.println(list.size());clear()会清空所有有效元素。7. ArrayList 的遍历方式ArrayList常见遍历方式有三种for循环 下标foreach迭代器7.1 for 循环 下标for(inti0;ilist.size();i){System.out.print(list.get(i) );}特点适合需要使用下标的场景。ArrayList支持随机访问因此这种方式很常用。7.2 foreach 遍历for(Integerinteger:list){System.out.print(integer );}特点写法简洁。适合只读取元素、不关心下标的场景。7.3 迭代器遍历IteratorIntegeritlist.listIterator();while(it.hasNext()){System.out.print(it.next() );}迭代器是一种设计模式在 Java 集合框架中被广泛使用。8. ArrayList 扩容机制8.1 为什么需要扩容ArrayList底层使用数组存储元素数组长度固定。当元素数量超过当前数组容量时需要申请更大的新数组并将旧数组中的元素复制过去。8.2 默认容量当使用无参构造创建ArrayList时底层最初是一个空数组。第一次添加元素时默认容量会扩展为10。privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA{};privatestaticfinalintDEFAULT_CAPACITY10;8.3 添加元素时的扩容流程publicbooleanadd(Ee){ensureCapacityInternal(size1);elementData[size]e;returntrue;}添加元素时核心流程如下判断当前容量是否足够。如果容量足够直接插入元素。如果容量不够调用扩容逻辑。扩容完成后将元素放入数组末尾。size加一。8.4 计算容量privatestaticintcalculateCapacity(Object[]elementData,intminCapacity){if(elementDataDEFAULTCAPACITY_EMPTY_ELEMENTDATA){returnMath.max(DEFAULT_CAPACITY,minCapacity);}returnminCapacity;}如果底层数组还是默认空数组第一次扩容时容量取DEFAULT_CAPACITY和minCapacity中较大的值。8.5 触发扩容privatevoidensureExplicitCapacity(intminCapacity){modCount;if(minCapacity-elementData.length0){grow(minCapacity);}}当minCapacity大于当前数组长度时调用grow进行扩容。8.6 扩容大小intoldCapacityelementData.length;intnewCapacityoldCapacity(oldCapacity1);扩容时新容量通常是旧容量的1.5倍。其中oldCapacity1表示旧容量除以2。所以newCapacityoldCapacityoldCapacity/2;8.7 特殊情况如果用户实际需要的容量超过预估的1.5倍容量则按照实际需要的容量扩容。if(newCapacity-minCapacity0){newCapacityminCapacity;}如果需要扩容的大小超过最大数组限制则重新计算容量。privatestaticfinalintMAX_ARRAY_SIZEInteger.MAX_VALUE-8;8.8 真正扩容elementDataArrays.copyOf(elementData,newCapacity);Arrays.copyOf会申请新空间并将旧数组中的元素复制到新数组中。8.9 扩容流程总结插入元素前检查容量是否足够。容量不够时进入扩容流程。默认按照旧容量的1.5倍扩容。如果1.5倍仍然不够则按实际需求容量扩容。扩容前检查是否超过最大数组限制。使用Arrays.copyOf完成新数组申请和数据复制。9. ArrayList 的问题与思考9.1 任意位置插入、删除效率低ArrayList底层使用连续空间。在任意位置插入或删除元素时需要整体搬移后续元素。时间复杂度O(N)9.2 扩容有额外开销扩容过程需要申请新空间。拷贝旧数据。释放旧空间。因此频繁扩容会带来时间和空间上的额外消耗。9.3 可能造成空间浪费扩容通常会申请比当前实际需求更大的空间。例如容量扩到较大后如果后续只插入少量数据剩余空间就会被浪费。9.4 改进方向针对这些问题可以考虑使用其他数据结构链表适合频繁插入、删除的场景。LinkedListJava 集合框架中的链式线性表实现。合理设置初始容量减少扩容次数。根据业务选择数据结构频繁随机访问优先考虑ArrayList频繁插入删除可以考虑链表。10. 重点速记线性表是具有相同特性的数据元素组成的有限序列。顺序表底层使用连续空间一般用数组实现。ArrayList本质是动态顺序表。ArrayList支持随机访问查询指定下标元素效率高。ArrayList任意位置插入、删除效率较低时间复杂度为O(N)。ArrayList无参构造时第一次添加元素会扩容到默认容量10。ArrayList扩容通常按1.5倍增长。ArrayList不是线程安全的。使用泛型可以限制集合中存储的元素类型避免类型混乱。subList(fromIndex, toIndex)截取范围是左闭右开区间[fromIndex, toIndex)。11. 易错点整理11.1 下标越界get、set、remove(index)都要求下标合法。合法范围通常是0 index size插入时add(index, element)的合法范围通常是0 index size11.2 remove 的重载问题ArrayList中remove有两个常见重载remove(intindex)remove(Objecto)对于ListInteger删除整数元素时容易混淆ListIntegerlistnewArrayList();list.add(1);list.add(2);list.add(3);list.remove(1);// 删除下标为 1 的元素list.remove(Integer.valueOf(1));// 删除元素 111.3 subList 不是完全独立的新 ArrayListsubList返回的是原列表的一部分视图与原列表有关联。修改原列表或子列表时要注意可能互相影响。11.4 泛型不能省略不推荐使用ListlistnewArrayList();推荐使用ListStringlistnewArrayList();12. 面试与考试常问问题12.1 ArrayList 底层是什么底层是数组。12.2 ArrayList 为什么支持随机访问因为底层数组空间连续可以通过下标直接计算元素位置。12.3 ArrayList 插入和删除为什么慢因为在中间位置插入或删除元素时需要搬移后续元素。12.4 ArrayList 默认容量是多少第一次添加元素时默认容量为10。12.5 ArrayList 如何扩容容量不足时通常扩容为旧容量的1.5倍并通过Arrays.copyOf拷贝数据。12.6 ArrayList 是否线程安全不是线程安全的。多线程场景可以考虑Vector或CopyOnWriteArrayList。12.7 ArrayList 和顺序表有什么关系ArrayList可以看作 Java 中动态顺序表的一种实现。

相关新闻

SteamShutdown:智能自动化助手,让游戏下载管理更轻松

SteamShutdown:智能自动化助手,让游戏下载管理更轻松

SteamShutdown:智能自动化助手,让游戏下载管理更轻松 【免费下载链接】SteamShutdown Automatic shutdown after Steam download(s) has finished. 项目地址: https://gitcode.com/gh_mirrors/st/SteamShutdown 还在为深夜等待游戏下载完成而烦恼…

2026/6/30 15:10:01阅读更多 →
匹配硕本博不同写作要求:gradpaper 毕业论文功能的精准适配逻辑

匹配硕本博不同写作要求:gradpaper 毕业论文功能的精准适配逻辑

Gradpaper-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/课程论文。 Gradpaper论文智能生成软件,10分钟生成万字毕业论文、期刊论文、文献综述、PPT,Agc查重、降重报告、文献资料。只需一个标题,从开题报告到答辩一键生成软件&…

2026/6/30 15:10:01阅读更多 →
Android SELinux权限调试实战:从avc denied到audit2allow精准修复

Android SELinux权限调试实战:从avc denied到audit2allow精准修复

1. 初识SELinux权限问题:从avc denied报错开始 第一次在Android开发中看到"SELinux: avc: denied"的日志时,我整个人都是懵的。这种报错通常长这样: type1400 audit(0.0:2346): avc: denied { write } for comm"com.test"…

2026/6/30 15:10:01阅读更多 →
CircuitPython与MicroPython的模块差异与兼容性实践

CircuitPython与MicroPython的模块差异与兼容性实践

1. CircuitPython与MicroPython的核心模块差异 第一次接触CircuitPython的开发者,往往会惊讶于它与MicroPython在模块设计上的巨大差异。虽然两者都源自Python的嵌入式实现,但在实际使用中你会发现,从MicroPython迁移项目到CircuitPython时&a…

2026/6/30 15:50:04阅读更多 →
网络安全最火的五个就业方向,来看看哪个是你的菜?

网络安全最火的五个就业方向,来看看哪个是你的菜?

网络安全最火的五个就业方向,来看看哪个是你的菜? 有人问:“我学会渗透测试是不是就能当黑客了?”这真是很多小白最大的盲区! 现在的网安行业分工多着呢,今天,咱们就来扒一扒网安行业最火的5个…

2026/6/30 15:50:04阅读更多 →
AI驱动研发流程的根本性变化解析

AI驱动研发流程的根本性变化解析

核心观点摘要 AI正在从代码生成等单点工具向端到端研发全链路渗透,腾讯内部数据显示AI辅助已覆盖超90%工程师,整体研发效能提升超20%研发流程智能化转型的核心价值在于消除跨域协作损耗,通过流程引擎串联需求、设计、开发、测试、发布、运营…

2026/6/30 15:50:04阅读更多 →
Prompt Learning 如何革新NLP?从“完形填空”到高效调优的演进之路

Prompt Learning 如何革新NLP?从“完形填空”到高效调优的演进之路

1. 从传统微调到Prompt Learning的范式转变 记得我第一次接触NLP任务时,导师扔给我一个情感分析数据集,要求用BERT模型实现分类。当时我按照教程,在BERT后面接了个全连接层,然后开始了漫长的微调过程。结果训练了三天三夜&#x…

2026/6/30 15:50:04阅读更多 →
Wireshark实战解析:UDP协议数据包捕获与深度剖析

Wireshark实战解析:UDP协议数据包捕获与深度剖析

1. UDP协议基础与Wireshark抓包准备 UDP协议作为传输层的核心协议之一,在日常网络应用中扮演着重要角色。与TCP不同,UDP采用无连接方式传输数据,这使得它在实时性要求高的场景中表现尤为突出。想象一下视频会议场景:当你在进行线上…

2026/6/30 15:50:04阅读更多 →
鸿蒙 App 如何设计 Agent Bus?一文讲透智能体通信机制

鸿蒙 App 如何设计 Agent Bus?一文讲透智能体通信机制

网罗开发(小红书、快手、视频号同名)大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方…

2026/6/30 15:45:04阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/6/30 4:03:30阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/6/30 4:36:27阅读更多 →
为什么你需要Destiny 2 Solo Enabler:技术原理与实战指南

为什么你需要Destiny 2 Solo Enabler:技术原理与实战指南

为什么你需要Destiny 2 Solo Enabler:技术原理与实战指南 【免费下载链接】Destiny-2-Solo-Enabler Repo containing the C# and XAML code for the D2SE program. Included is also the dependency for the program, and image asset. 项目地址: https://gitcode…

2026/6/30 0:02:58阅读更多 →
第六章:PowerPoint 2010 核心功能与实战应用 —— 从入门到精通

第六章:PowerPoint 2010 核心功能与实战应用 —— 从入门到精通

1. PowerPoint 2010基础操作全攻略 刚接触PowerPoint 2010时,很多人会被它复杂的界面吓到。其实只要掌握几个核心区域,就能快速上手。我最开始用PPT时,经常找不到功能按钮在哪,后来发现主要操作都集中在顶部功能区。 工作窗口主要…

2026/6/30 0:02:58阅读更多 →
XGBoost超参数实战:从理论到调优策略

XGBoost超参数实战:从理论到调优策略

1. XGBoost超参数基础认知 第一次接触XGBoost时,我被它那密密麻麻的参数列表吓到了。这感觉就像面对一架波音747的驾驶舱——每个按钮都可能有神奇的效果,但按错了就可能坠机。经过多年实战,我发现其实掌握十几个核心参数就能解决90%的问题。…

2026/6/30 0:02:59阅读更多 →