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

Java数据结构之ArrayList

 一、ArrayList 是什么?

ArrayList 是一个可动态扩容的数组容器,实现了 List 接口,底层基于对象数组实现。

它解决了普通数组长度固定的问题,允许你在运行时动态添加、删除元素。

import java.util.ArrayList;ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
System.out.println(list); // [Java, Python]

二、核心特性

特性说明
有序元素按插入顺序存储
可重复允许重复元素
索引访问支持通过索引(0-based)快速访问
线程不安全非同步,多线程需手动同步或使用 Collections.synchronizedList
允许 null可以存储 null 值
自动扩容当容量不足时自动增长(通常1.5倍)

三、底层结构:基于数组

ArrayList 的本质是一个动态数组

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {transient Object[] elementData; // 存储元素的底层数组(非私有是为了序列化优化)private int size;               // 当前元素个数
}
  • elementData:是一个 Object[] 数组,用来存放元素。
  • size:记录当前实际存储的元素个数,不等于数组长度elementData.length)。

 所以 ArrayList 支持随机访问(Random Access),时间复杂度 O(1)。


四、构造方法

1. 无参构造(最常用)

ArrayList<String> list = new ArrayList<>();
// 初始容量为 0,第一次 add 时才扩容为 10(JDK 1.8+ 懒加载)

2. 指定初始容量

ArrayList<String> list = new ArrayList<>(20); // 初始容量为20

3. 从集合构造

List<String> copy = new ArrayList<>(otherList);

提示:如果预估元素数量,建议指定初始容量,避免频繁扩容带来的性能开销。


五、添加元素:add(E e)

list.add("Hello");

执行流程:

  1. 检查是否需要扩容
    • ensureCapacityInternal(size + 1)
  2. 将元素放入 elementData[size]
  3. size++

扩容机制(关键!)

// 扩容公式:新容量 = 旧容量 + 旧容量右移1位(即 1.5倍)
int newCapacity = oldCapacity + (oldCapacity >> 1);

例如:

  • 从 10 → 15 → 22 → 33 → 49 → ...

扩容会触发 Arrays.copyOf(),创建新数组并复制数据,时间复杂度 O(n),所以应尽量避免频繁扩容。


 六、随机访问 vs 插入/删除

操作时间复杂度说明
get(index)O(1)直接通过数组下标访问
set(index, e)O(1)修改指定位置元素
add(e)均摊 O(1)尾部添加,偶尔扩容 O(n)
add(index, e)O(n)需要移动后续元素
remove(index)O(n)需要移动后续元素
contains(e)O(n)需要遍历查找

所以:ArrayList 适合读多写少、尾部操作多的场景。


 七、删除元素

list.remove(0);        // 按索引删除
list.remove("Java");   // 按对象删除(删除第一个匹配项)
  • 删除后会将后面的元素向前移动
  • 不会自动缩容(除非手动调用 trimToSize())。

 八、遍历方式(推荐与陷阱)

推荐方式:

// 1. 增强for(最常用)
for (String s : list) { ... }// 2. 迭代器(安全删除)
Iterator<String> it = list.iterator();
while (it.hasNext()) {if (it.next().equals("delete")) {it.remove(); //  安全删除}
}// 3. Stream(函数式)
list.stream().forEach(System.out::println);

错误方式(并发修改异常):

for (int i = 0; i < list.size(); i++) {if (list.get(i).equals("bad")) {list.remove(i); // 可能出错或漏删}
}

问题:删除后索引错位,且会触发 ConcurrentModificationException(fail-fast 机制)。


 九、fail-fast 机制

ArrayList 在迭代过程中如果被其他线程或当前线程修改,会抛出 ConcurrentModificationException

modCount++; // 修改次数计数器

迭代器在每次 next() 前会检查 modCount == expectedModCount,不一致就抛异常。

解决方案:使用 Iterator.remove()CopyOnWriteArrayList(并发场景)。


十、ArrayList vs 数组 vs LinkedList(下期说LinkedList)

对比项数组ArrayListLinkedList
大小固定动态动态
访问速度 O(1) O(1)O(n)
插入/删除O(n)O(n) O(1)(已知位置)
内存开销中等大(双向指针)
底层结构连续数组对象数组双向链表
是否支持随机访问是(但慢)

十一、一些理论知识

  1. ArrayList 扩容机制?

    答:初始容量10(懒加载),每次扩容为 1.5倍,使用 Arrays.copyOf 复制。

  2. 如何实现线程安全的 ArrayList?

    答:Collections.synchronizedList(new ArrayList<>()) 或使用 CopyOnWriteArrayList

  3. ArrayList 和 Vector 的区别?

    Vector 是线程安全的(方法加 synchronized),但性能差;ArrayList 非线程安全。

  4. 如何删除 ArrayList 中的重复元素?

    List<String> distinct = new ArrayList<>(new LinkedHashSet<>(list));

 总结:ArrayList 是:

  • 底层是 Object[] 数组,支持随机访问。
  • 自动扩容(1.5倍),但扩容成本高。
  • 线程不安全,适合单线程场景。
  • 尾部操作高效,中间插入/删除慢。
  • 是 List 接口最常用实现。

散会

http://www.dtcms.com/a/327497.html

相关文章:

  • 《算法导论》第 20 章 - van Emde Boas 树
  • 《前端性能监控深解:从指标捕获到数据洞察的完整脉络》
  • Windows已经安装了一个MySQL8,通过修改配置文件的端口号跑2个或多个Mysql服务方法,并注册为系统服务
  • linux远程部署dify和mac本地部署dify
  • 【3】Transformers快速入门:大语言模型LLM是啥?
  • 电商双 11 美妆数据分析总结
  • 自然语言处理( NLP)基础
  • Elasticsearch Node.js 客户端连接指南(Connecting)
  • 2025年最新原创多目标算法:多目标酶作用优化算法(MOEAO)求解MaF1-MaF15及工程应用---盘式制动器设计,提供完整MATLAB代码
  • 机器学习算法篇(十):TF-IDF算法详解与应用实战
  • 成都影像产业园实训考察:重庆五一职院关注技能就业
  • 人大BABEC地平线高效率具身导航!Aux-Think:探索视觉语言导航中数据高效的推理策略
  • PaddlePaddle 模型训练技巧
  • 深入C#异步编程基石:BeginInvoke与EndInvoke全解析
  • 代码随想录算法训练营四十二天|单调栈part02
  • 【Activiti】要点初探
  • 迈向具身智体人工智能:LLM 和 VLM 驱动的机器人自主性和交互性
  • 11-docker单机版的容器编排工具docker-compose基本使用
  • Qt中定时器介绍和使用
  • 文字转语音 edge_tts
  • Spring IoC实现原理详解
  • [激光原理与应用-251]:理论 - 几何光学 - 长焦与短焦的比较
  • 晶片与电路板的桥梁-封装
  • 回归预测 | Matlab实现CNN-BiLSTM-self-Attention多变量回归预测
  • 外卖投诉:差评转复购的3步攻略
  • DOM2 Style的隐藏武器:getComputedStyle()的使用指南
  • idea git commit特别慢,cpu100%
  • dag实现案例 02、实现简易版dag调度系统(基于01之上升级)
  • GeoScene 空间大数据产品使用入门(6)进阶模型
  • 软考备考(三)