上一篇
java怎么定义动态数组
- 后端开发
- 2025-08-06
- 44
在 Java 中可通过
ArrayList 实现动态数组,需导入
java.util.ArrayList,`List list = new
在 Java 中,传统意义上的“原生数组”(如 int[] arr = new int[5];)一旦创建,其长度便不可更改,若需实现类似“动态数组”的功能(即可根据需求自动扩展或收缩的数组),主要有以下几种核心方案及最佳实践:
一、最主流方案:使用 java.util.ArrayList(推荐)
ArrayList 是 Java 集合框架提供的 动态数组实现类,底层基于原生数组,但封装了自动扩容逻辑,并提供丰富的 API。

关键特性与操作详解
| 操作 | 描述 | 示例代码 | 备注 |
|---|---|---|---|
| 创建空列表 | 新建一个无初始容量的动态数组 | List<Integer> list = new ArrayList<>(); |
默认初始容量约10,满后自动扩容至1.5倍 |
| 指定初始容量 | 预分配足够空间减少后续扩容次数 | new ArrayList<>(20); |
适合已知大致数据量的场景 |
| 添加元素 | 向列表末尾追加元素 | list.add(42); |
时间复杂度 O(1)(均摊) |
| 插入元素 | 在指定位置插入元素 | list.add(1, "Hello"); |
后续元素后移,时间复杂度 O(n) |
| 获取元素 | 根据索引获取元素 | Integer num = list.get(0); |
索引从0开始,越界抛 IndexOutOfBoundsException |
| 修改元素 | 更新指定位置的元素 | list.set(2, 99); |
原位置元素被覆盖 |
| 删除元素 | 移除指定位置或对象的第一个匹配项 | list.remove(0); / list.remove("A"); |
时间复杂度 O(n) |
| 清空列表 | 保留容器,清除所有元素 | list.clear(); |
不等于重新创建新列表 |
| 获取大小 | 返回当前元素个数 | int size = list.size(); |
区别于原生数组的 length 属性 |
| 转换为数组 | 将列表转为原生数组 | Object[] arr = list.toArray(); |
若需特定类型需强制转换 |
️ 注意事项
- 类型安全:必须指定泛型类型(如
ArrayList<String>),否则需显式类型转换。 - 失败快速:尝试访问不存在的索引会直接抛出异常,建议先用
size()判断。 - 内存效率:频繁增删可能导致多次扩容/缩容,可预估初始容量优化性能。
示例完整代码
import java.util.ArrayList;
import java.util.List;
public class DynamicArrayExample {
public static void main(String[] args) {
// 创建初始容量为5的整型动态数组
List<Integer> dynamicArray = new ArrayList<>(5);
// 添加元素(自动扩容)
dynamicArray.add(10); // [10]
dynamicArray.add(20); // [10, 20]
dynamicArray.add(30); // [10, 20, 30]
// 插入元素到索引1的位置
dynamicArray.add(1, 15); // [10, 15, 20, 30]
// 修改索引2的元素
dynamicArray.set(2, 25); // [10, 15, 25, 30]
// 删除索引1的元素
dynamicArray.remove(1); // [10, 25, 30]
// 遍历打印所有元素
for (Integer num : dynamicArray) {
System.out.println(num); // 输出:10, 25, 30
}
// 转换为原生数组
Integer[] nativeArray = dynamicArray.toArray(new Integer[0]);
System.out.println("原生数组长度:" + nativeArray.length); // 输出:3
}
}
️ 二、手动模拟动态数组(学习目的)
若不使用 ArrayList,可通过以下方式模拟动态数组的行为:
核心思路
- 维护内部缓冲区:使用原生数组存储数据。
- 跟踪有效长度:单独变量记录当前元素数量。
- 自动扩容策略:当空间不足时,创建更大的新数组并复制旧数据。
简易实现示例
public class ManualDynamicArray {
private int[] data; // 内部存储数组
private int size; // 当前元素个数
private static final int DEFAULT_CAPACITY = 10;
public ManualDynamicArray() {
data = new int[DEFAULT_CAPACITY];
size = 0;
}
// 添加元素(核心方法)
public void add(int element) {
if (size == data.length) {
// 扩容:创建新数组(容量翻倍)
int newCapacity = data.length 2;
int[] newData = new int[newCapacity];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = element;
}
// 获取元素
public int get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
return data[index];
}
// 获取当前元素个数
public int size() {
return size;
}
}
️ 局限性说明
- 此实现仅包含基础功能,缺少
ArrayList的完整特性(如中间插入、删除、迭代器等)。 - 实际开发中强烈建议直接使用
ArrayList,此处仅为演示原理。
️ 三、与其他结构的对比选择
| 结构 | 动态数组能力 | 随机访问速度 | 插入/删除效率 | 适用场景 |
|---|---|---|---|---|
ArrayList |
O(1) | O(n) | 频繁读操作,少量写 | |
LinkedList |
O(n) | O(1) | 频繁插入/删除 | |
HashSet/TreeSet |
N/A | O(1)/O(log n) | 无序/有序唯一性存储 | |
Vector |
O(1) | O(n) | 老旧类,已被 ArrayList 取代 |
四、常见问题解答(FAQs)
Q1: ArrayList 的初始容量设置多大合适?
A: 根据业务场景预估,若已知数据量接近某个数值(如1000),可直接设置初始容量为该值以避免多次扩容,若不确定,使用默认构造函数即可,Java会自动处理扩容,盲目设置过大容量会浪费内存。

Q2: 如何将 ArrayList 转换为基本类型数组?(如 int[])
A: 由于泛型擦除机制,需借助流式API或循环手动转换:
// 方法1:使用流(Java 8+)
List<Integer> list = Arrays.asList(1, 2, 3);
int[] primitiveArray = list.stream().mapToInt(Integer::intValue).toArray();
// 方法2:循环转换
int[] arr = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
arr[i] = list.get(i);
}
注意:直接调用 toArray() 返回的是 Object[],无法直接转为基本类型

