当前位置: 首页 > 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.xdnf.cn/news/1285939.html

相关文章:

  • [激光原理与应用-256]:理论 - 几何光学 - CMOS与CCD传感器成像原理比较
  • 卫生间装修防水怎么做合适?
  • 激光干涉法在碳化硅衬底 TTV 厚度测量中的精度提升策略
  • 高性能web服务器Tomcat
  • Vue 3 + Elementui + TypeScript 实现左侧菜单定位右侧内容
  • 石英加速度计如何实现高精度测量?
  • 深度贴:前端网络基础及进阶(3)
  • 鲲鹏arm服务器安装neo4j社区版,实现图书库自然语言检索基础
  • 地图可视化实践录:显示地理区域图
  • 自然语言处理关键库解析和使用方法- FuzzyWuzzy
  • 虚拟机一站式部署Claude Code 可视化UI界面
  • 豆包 + 蘑兔 AI:你的创作搭子
  • 运维学习Day22——Anisible自动化与基本使用
  • Kafka的一条消息的写入和读取过程原理介绍
  • kafka 消费者组的概念是什么?它是如何实现消息的点对点和发布/订阅模式?
  • PO、BO、VO、DTO、POJO、DAO、DO基本概念
  • 开源!!! htop移植到OpenHarmony
  • 【网络运维】Linux和自动化: Ansible基础实践
  • ncurses 6.5 交叉编译移植到OpenHarmomy
  • 【软考中级网络工程师】知识点之 IP QoS 技术
  • 小红书笔记信息获取_实在智能RPA源码解读
  • 【Redis优化深度剖析:如何通过读写分离提升系统性能】
  • 【限时分享:Hadoop+Spark+Vue技术栈电信客服数据分析系统完整实现方案
  • Rocky Linux 10 部署 Kafka 集群
  • Bevy渲染引擎核心技术深度解析:架构、体积雾与Meshlet渲染
  • AI-调查研究-49-大数据调研报告 发展历程:从概念诞生到多元化生态1997-2025
  • msyql中,max_connections和max_user_connections区别
  • 【DL】深层神经网络
  • 记录docker使用kong consul postgresql配置dns异常解决
  • SQL180 每类试卷得分前3名