Java数据结构——ArrayList
Java中ArrayList
- 一 ArrayList的简介
- 二 ArrayList的构造方法
- 三 ArrayList常用方法
- 1.add()方法
- 2.remove()方法
- 3.get()和set()方法
- 4.index()方法
- 5.subList截取方法
- 四 ArrayList的遍历
- for循环遍历
- 增强for循环(for each)
- 迭代器遍历
- ArrayList问题及其思考
前言
ArrayList是一种 顺序表,⽤⼀段 物理地址连续的存储单元依次存储数据的线性结构,一般情况都是采用数组存储,在数组上实现一些增删查改等等功能, ArrayList是Java中最常用的 动态数组实现之一,其内部的内存空间是可以改变的,今天就来探究一下ArrayList使用及其原理

一 ArrayList的简介
ArrayList虽然是一个普通的类,但是它实现了List接口
List接口在JDK17的部分源码

ArrayList类在JDK17的部分源码

我们可以从上面看出
1. List是一个接口,继承了Collection类
2. ArrayList是一个类,继承了AbstractList类
3. ArrayList实现了List中的RandomAccess接口,说明其支持随机访问
4. 实现了Cloneable接口,说明其支持clone
5. 实现了Serializable接口,说明其支持序列化
下面是ArrayList的一些常用方法,因为其实现了List接口,所以List中的抽象方法,在ArrayList都有

二 ArrayList的构造方法
| ArrayList () | 无参构造 |
|---|---|
| ArrayList (int initialCapacity) | 确定初始容量 |
| ArrayList (Collection<? extends E> c) | 利用其他Collection来构造 |
public class Test {public static void main(String[] args) {//1.无参构造List<Integer> list = new ArrayList<>();//2.含参构造,确定其初始化的容量,确定其初始化容量为1List<Integer> list1 = new ArrayList<>(1);//3.利用其他构造//这里list2与list的元素一致List<Integer> list2 = new ArrayList<>(list);}
}
无参构造源码


虽然无参构造没有给定容量,但是编译器会默认一个容量,JDK17中默认容量为10
含初始容量一个参数的构造

如果给定初始容量,编译器会进行判断,如果初始容量>0就按照你给定的容量创建对象,如果初始容量==0就按照默认的容量进行创建,反之如果<0就抛出容量不合法的异常
注意在创建线性表的时候,要指定是什么类型的线性表
1.如果不写类型,编译器会报错,因为其不知道是什么类型

2.并且其必须是包装类型
如果写成普通类型编译器也会报错

3.那何为包装类型呢
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
这些类型中除了int和char的包装类有所改变,其他的都是基本类型的首字母大写
三 ArrayList常用方法
| 方法 | 解释 |
|---|---|
| boolean add(E e) | 尾插 e |
| void add(int index, E e) | 将 e插入到 index 位置 |
| boolean addAll(Collection<? extends E> c) | 尾插 c 中的全部元素 |
| E remove(int index) | 删除 index 下标元素 |
| boolean remove(Object o) | 删除遇到的第一个 o |
| E get(int index) | 获取下标 index 下标元素 |
| E set(int index, E e) | 将下标 index 下标元素设置为 e |
| void clear() | 清空列表 |
| boolean contains(Object o) | 判断 o 是否在线性表中 |
| int indexOf(Object o) | 返回第一个 o 所在下标 |
| int lastIndexOf(Object o) | 返回最后一个 o 的下标 |
| List subList(int fromIndex, int toIndex) | 截取部分 list |
| int size() | 返回此列表中的实际的元素数 |
1.add()方法
boolean add(E e)
将指定的元素追加到此列表的末尾。
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);System.out.println(list);}
}
运行结果如下

注意这里的如果已经确定了是那种包装类型,就不可以在添加其他的包装类型的数据了

public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>(3);list.add(1);list.add(2);list.add(3);System.out.println("扩容前长度"+list.size());list.add(4);System.out.println("扩容后长度"+list.size());System.out.println(list);}
}
运行结果如下

我们发现一个问题就是上面我们初始化容量为3,但是我们添加了4个元素其并没有报错,为什么呢?那是因为其ArrayList类add方法中有扩容操作,但是这里的真实长度变为4

void add(int index, E e)
在index下标插入e
index>=0&&index<=其列表的长度
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);//在1下标插入99list.add(1,99);// list.add(4,1);System.out.println(list);}
}
我们要注意这里并不是简单替换,而是将某一个下标修改为一个数后,原本的数要往后偏移
偏移的同时其如果存储不下,也会进行扩容
运行结果如下

注意这里的下标要合法 index下标>=0&&index<=list.size()
这里等于其list的容量也可以,因为这样正好就相当于上面一个参数的add进行尾插

如果大于list.size()就会出现数组越界异常
这里长度为3,这里index>=0&&index<=3,因此这里出现数组越界异常异常了

boolean addAll(Collection<? extends E> c)
将指定集合中的所有元素追加到此列表的末尾
这里是可以自己尾插自己的
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);System.out.println("尾插前list"+list);List<Integer> list1 = new ArrayList<>();list1.add(10);list1.add(20);list1.add(30);//将list1尾插到list后面list.addAll(list1);System.out.println("尾插后list"+list);}
}

这里其实也是可以自己尾插自己的
下面这个自己尾插自己成功了

注意这里是不可以不同类型的列表进行尾插
一个列表中不可以放两种包装类型一样,尾插不同类型的肯定会报错

2.remove()方法
E remove(int index)
删除 index 下标元素
index>=0&&index<列表长度
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);//删除1下标的值list.remove(1);System.out.println(list);}
}
这里删除1下标的值,也就是删除这里的2
运行结果如下

boolean remove(Object o)
删除遇到的第一个 o
在使用的时候要将一个数装箱以后再进行删除
这里直接使用基本类型就是删除的是对应下标的值,而不是自己想要的

这时候就要进行装箱操作,这样就可以删除对应的值了,删除的就不是下标对应的值了
这里就是删除第一个出现的1元素,而不是下标,所以这里0下标的1被删除了

void clear()
清空列表
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);//删除1下标的值Integer a = 1;list.remove(a);System.out.println(list);list.clear();System.out.println("清空后"+list);}
}
这里就是将其置为空

3.get()和set()方法
E get(int index)
获取下标 index 下标元素E set(int index, E e)
将下标 index 下标元素设置为 e
index>=0&&index<列表长度
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);System.out.println("获取1下标的值:"+list.get(1));list.set(1,999);System.out.println("修改后1下标的值:"+list.get(1));}
}
这里和add方法不同的是,这个是直接修改值,而add是添加值
运行结果如下

4.index()方法
int indexOf(Object o) 返回第一个 o 所在下标
int lastIndexOf(Object o) 返回最后一个 o 的下标
找不到就返回-1
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(1);System.out.println("第一个元素1的下标:"+list.indexOf(1));//0//如果没有找到就返回-1System.out.println(list.indexOf(100));//-1System.out.println("最后一个元素1的下标:"+list.lastIndexOf(1));}
}

5.subList截取方法
List subList(int fromIndex, int toIndex)
截取下标[fromIndex,toIndex]的list
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);List<Integer> list1 = list.subList(1,3);//这里是左闭右开的截取方法System.out.println("截取[1,3)下标的元素:"+list1);}
}
运行结果如下

其实这里并不是真正的截取
例如:
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);List<Integer> list1 = list.subList(1,3);//这里是左闭右开的截取方法System.out.println("截取[1,3)下标的元素:"+list1);list1.remove(0);//删除list1中的0下标的值也就是2System.out.println("被截取的list: "+ list);}
}
这里删除截取中0下标的2,而原本的list中的2也被删除了
运行结果如下

可以看出这里我们对截取的内容删除,导致了list中的这部分内容也被删除了

只是将其一个对象指向截取的部分,只是将其截取部分的地址放入一个新对象中,因此对截取修改也会影响原本的list
四 ArrayList的遍历
for循环遍历
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);for (int i = 0; i < list.size(); i++) {//获取下标对应的值System.out.print(list.get(i)+" ");}}
}
这里的size()获取其列表长度
进行一个一个下标遍历就行
运行结果如下

增强for循环(for each)
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);//每个元素的类型为Integerfor (Integer integer:list) {System.out.print(integer+" ");}}
}
这里使用for-each遍历,这里列表中元素类型都为Integer,就用一个临时integer来访问和打印

迭代器遍历
public class Test {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);//使用迭代器//从前向后遍历Iterator<Integer> it = list.iterator();//获取其开始位置while(it.hasNext()){//不断的往后走System.out.print(it.next()+" ");}System.out.println();//从后向前遍历给定其下标从其最后面开始ListIterator<Integer> it1 = list.listIterator(list.size());while (it1.hasPrevious()){System.out.print(it1.previous()+" ");}System.out.println();}
}
运行结果如下

ArrayList问题及其思考
1.在其查找数据是非常简单和高效的
2.但是,ArrayList列表在添加或者删除元素的时候,都需要将其后面的数据向前移动,时间复杂度为O(N)
3.在添加数据时候可能会扩容,是1.5倍数扩容,有点浪费空间
因此还需要其他的数据结构来完成添加或者删除元素会更高效一点
相关文章:
Java数据结构——ArrayList
Java中ArrayList 一 ArrayList的简介二 ArrayList的构造方法三 ArrayList常用方法1.add()方法2.remove()方法3.get()和set()方法4.index()方法5.subList截取方法 四 ArrayList的遍历for循环遍历增强for循环(for each)迭代器遍历 ArrayList问题及其思考 前言 ArrayList是一种 顺…...
科学量化AI对品牌产品印象 首个AI印象(AII)指数发布
2025年4月18日,营销传播数据研究领先机构四度传播研究院(SAC),正式推出了量化AI大模型对产品整体印象的AI印象,简称AII(ARTIFICIAL INTELLIGENCE IMPRESSIONS),同时发布了首个“汽车AI印象榜”。为企业和消…...
Python语法系列博客 · 第8期[特殊字符] Lambda函数与高阶函数:函数式编程初体验
上一期小练习解答(第7期回顾) ✅ 练习1:找出1~100中能被3或5整除的数 result [x for x in range(1, 101) if x % 3 0 or x % 5 0]✅ 练习2:生成字符串长度字典 words ["apple", "banana", "grape…...
FFmpeg 硬核指南:从底层架构到播放器全链路开发实战 基础
目录 1.ffmpeg的基本组成2.播放器的API2.1 复用器阶段2.1.1 分配解复用上下文2.1.2 文件信息操作2.1.3 综合示例 2. 2 编解码部分2.2.1 分配解码器上下文2.2.2编解码操作2.2.3 综合示例 3 ffmpeg 内存模型3.1 基本概念3.2API 1.ffmpeg的基本组成 模块名称功能描述主要用途AVFo…...
大数据建模与评估
文章目录 实战案例:电商用户分群与价值预测核心工具与库总结一、常见数据挖掘模型原理及应用(一)决策树模型(二)随机森林模型(三)支持向量机(SVM)模型(四)K - Means聚类模型(五)K - Nearest Neighbors(KNN)模型二、运用Python机器学习知识实现数据建模与评估(一…...
UE5有些场景的导航生成失败解决方法
如果导航丢失,就在项目设置下将: 即可解决问题: 看了半个小时的导航生成代码发现,NavDataSet这个数组为空,导致异步构建导航失败。 解决 NavDataSet 空 无法生成如下: 当 NavDataSet 为空的化 如果 bAut…...
MCP(Model Context Protocol 模型上下文协议)科普
MCP(Model Context Protocol,模型上下文协议)是由人工智能公司 Anthropic 于 2024年11月 推出的开放标准协议,旨在为大型语言模型(LLM)与外部数据源、工具及服务提供标准化连接,从而提升AI在实际…...
健康养生指南
在快节奏的现代生活中,健康养生成为人们关注的焦点。它不仅关乎身体的强健,更是提升生活质量、预防疾病的关键。掌握科学的养生方法,能让我们在岁月流转中始终保持活力。 饮食是健康养生的基础。遵循 “均衡膳食” 原则,每日饮食需…...
Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)
本节目标 理解进程终止的概念理解退出状态码的概念以及使用方法掌握_exit与exit函数的用法以及区别atexit函数注册终止时执行的函数相关宏 一、进程终止 进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源&a…...
Linux下 文件的查找、复制、移动和解压缩
1、在/var/log目录下创建一个hehe.log的文件,其文件内容是: myhostname ghl mydomain localdomain relayhost [smtp.qq.com]:587 smtp_use_tls yes smtp_sasl_auth_enable yes smtp_sasl_security_options noanonymous smtp_sasl_tls_security_opt…...
C语言学习之预处理指令
目录 预定义符号 #define的应用 #define定义常量 #define定义宏 带有副作用的宏参数 宏替换的规则 函数和宏定义的区别 #和## #运算符 ##运算符 命名约定 #undef 编辑 命令行定义 条件编译 头文件包含 头文件被包含的方式 1.本地头文件包含 2.库文件包含 …...
【STM32单片机】#10 USART串口通信
主要参考学习资料: B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…...
fastlio用mid360录制的bag包离线建图,提示消息类型错误
我用mid360录制的bag包,激光雷达的数据类型是sensor_msgs::PointCloud2,但是运行fast_lio中的mid360 launch文件,会报错(没截图),显示无法从livox_ros_driver2::CustomMsg转换到sensor_msgs::PointCloud2。…...
二级评论列表-Java实现
二级评论列表是很常见的功能,文章记录了新手用Java实现的具体逻辑。 整体实现逻辑是先用2个sql,分别查出两层数据。然后用java在service中实现数据组装,返给前端。这种实现思路好处是SQL简洁,逻辑分明,便于维护。 一…...
IP检测工具“ipjiance”
目录 IP质量检测 应用场景 对网络安全的贡献 对网络管理的帮助 对用户决策的辅助作用 IP质量检测 检测IP的网络提供商:通过ASN(自治系统编号)识别IP地址所属的网络运营商,例如电信、移动、联通等。 识别网络类型࿱…...
mysql的函数(第二期)
九、窗口函数(MySQL 8.0) 适用于对结果集的子集(窗口)进行计算,常用于数据分析场景。 ROW_NUMBER() 作用:为每一行生成唯一的序号。示例:按分数降序排名 SELECT n…...
Replicate Python client
本文翻译整理自:https://github.com/replicate/replicate-python 文章目录 一、关于 Replicate Python 客户端相关链接资源关键功能特性 二、1.0.0 版本的重大变更三、安装与配置1、系统要求2、安装3、认证配置 四、核心功能1、运行模型2、异步IO支持3、流式输出模型…...
halcon模板匹配(八)alignment_for_ocr_in_semiconductor
目录 一、alignment_for_ocr_in_semiconductor例程目的二、创建训练和查找用于图像对齐三、图像对齐四、在指定区域内查找文本一、alignment_for_ocr_in_semiconductor例程目的 在一个图像中定义两个区域,一个用于图像对齐,在另一个区域内使用文本模板进行匹配。 二、创建训…...
Java读取JSON文件并将其中元素转为JSON对象输出
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Java读取JSON文件并将其中元素转为JSON对象输…...
华为openEuler操作系统全解析:起源、特性与生态对比
华为openEuler操作系统全解析:起源、特性与生态对比 一、起源与发展历程 openEuler(欧拉操作系统)是华为于2019年开源的Linux发行版,其前身为华为内部研发的服务器操作系统EulerOS。EulerOS自2010年起逐步发展,支持华…...
Elasticsearch使用及常见的问题
Elasticsearch作为一款分布式搜索与分析引擎,其核心优势在于高性能搜索能力,依托倒排索引和分布式架构,可快速处理海量数据及复杂查询,支持实时索引与动态扩容,兼具高可用性和扩展性。其丰富的RESTful API与查询语言降…...
Python基础总结(七)之条件语句
文章目录 条件语句if一、Python中的真假二、条件语句格式2.1 if语句格式2.2 if-else语句2.3 if-elif-else语句 三、if语句嵌套 条件语句if 条件语句其实就是if语句,在讲解if语句之前需要知道Python中对于真假的判断。 一、Python中的真假 在Python中非0的都为真&…...
命令update-alternatives
❯ which pip /home/ying/anaconda3/bin/pipying192 ~ [2]> which pip /usr/bin/pip使用update-alternatives对他们进行管理和切换 快捷方式 和 实际路径不可以相同 所以我这边选择了/usr/local/bin目录作为介质存储快捷方式,另外该快捷方式会自己创建我们只需选…...
deekseak 本地windows 10 部署步骤
有些场景需要本地部署,例如金融、医疗(HIPAA)、政府(GDPR)、军工等,需完全控制数据存储和访问权限,避免云端合规风险或者偏远地区、船舶、矿井等无法依赖云服务,关键设施(…...
MySQL中常用函数的分类及示例
概述 以下是 MySQL 中常用函数的分类及示例,涵盖字符串处理、数值计算、日期操作、条件判断等常见场景: 一、字符串函数 1. CONCAT(str1, str2, ...) 拼接字符串。 SELECT CONCAT(Hello, , World); -- 输出: Hello World2. SUBSTRING(str, start,…...
<sql>、<resultMap>、<where>、<foreach>、<trim>、<set>等标签的作用和用法
目录 一. sql 代码片段标签 二. resultMap 映射结果集标签 三. where 条件标签 四. set 修改标签 五. trim 标签 六. foreach 循环标签 一. sql 代码片段标签 sql 标签是 mybatis 框架中一个非常常用的标签页,特别是当一张表很有多个字段多,或者要…...
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置)
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置) 摘要:本文深入讲解在离线环境下部署HAProxy 3.1.1的全流程,涵盖源码编译、系统服务封装、K8S APIServer四层负载配置等核心环节,并提供生产级高…...
实现Azure Databricks安全地请求企业内部API返回数据
需要编写一个Databricks在Azure云上运行,它需要访问企业内部的API获取JSON格式的数据,企业有网关和防火墙,API有公司的okta身份认证,通过公司的域账号来授权访问,现在需要创建一个专用的域账号,让Databrick…...
kafka认证部署
首先启动 zookeeper /home/kafka/bin/zookeeper-server-start.sh /home/kafka/config/zookeeper.properties 创建SCRAM证书 /home/kafka/bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config SCRAM-SHA-256[iterations8192,passwordliebe],SCRAM-SHA-512[p…...
【项目】CherrySudio配置MCP服务器
CherrySudio配置MCP服务器 (一)Cherry Studio介绍(二)MCP服务环境搭建(1)环境准备(2)依赖组件安装<1> Bun和UV安装 (3)MCP服务器使用<1> 搜索MCP…...
