1. 概述
Java 中的数组一旦创建,其长度是不可变的。如果想“扩展”数组长度,实际上只能通过创建一个新的更长数组,并将旧数组内容复制进去来实现。
本文将介绍几种扩展 Java 数组长度的常见做法,包括使用 Arrays.copyOf
、ArrayList
、以及 System.arraycopy
等方法。虽然看起来有点基础,但实际使用中还是有些细节需要注意,特别是性能和类型处理方面。
2. 使用 Arrays.copyOf
这是最简单直接的一种方式,借助 Arrays.copyOf
方法可以快速完成数组扩容。
示例代码如下:
public Integer[] addElementUsingArraysCopyOf(Integer[] srcArray, int elementToAdd) {
Integer[] destArray = Arrays.copyOf(srcArray, srcArray.length + 1);
destArray[destArray.length - 1] = elementToAdd;
return destArray;
}
✅ 优点:代码简洁,语义清晰
❌ 注意点:
- 如果目标数组长度大于源数组,
Arrays.copyOf
会自动填充默认值(如null
、0
、false
)。 - 对于基本数据类型和包装类,填充值不同,需注意类型差异。
3. 使用 ArrayList
如果你更习惯使用集合类,也可以借助 ArrayList
来实现数组扩容。
步骤如下:
- 将原始数组转为
ArrayList
- 添加新元素
- 再转回数组
代码如下:
public Integer[] addElementUsingArrayList(Integer[] srcArray, int elementToAdd) {
Integer[] destArray = new Integer[srcArray.length + 1];
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(srcArray));
arrayList.add(elementToAdd);
return arrayList.toArray(destArray);
}
✅ 优点:逻辑清晰,适合需要频繁增删的场景
❌ 注意点:
Arrays.asList()
返回的是一个固定大小的List
,不能直接扩容ArrayList.toArray()
需要传入一个目标数组用于填充
4. 使用 System.arraycopy
这是最底层也是性能最好的方式,适合对性能有要求的场景。
示例代码如下:
public Integer[] addElementUsingSystemArrayCopy(Integer[] srcArray, int elementToAdd) {
Integer[] destArray = new Integer[srcArray.length + 1];
System.arraycopy(srcArray, 0, destArray, 0, srcArray.length);
destArray[destArray.length - 1] = elementToAdd;
return destArray;
}
✅ 优点:效率高,控制灵活
❌ 注意点:
- 参数顺序容易写错,注意是
src, srcPos, dest, destPos, length
Arrays.copyOf
实际上内部也是调用了System.arraycopy
5. 性能比较与建议
所有方法本质上都做了同一件事:创建新数组并复制内容。
⚠️ 因为数组是连续内存结构,扩容只能重新申请一块更大的内存空间,所以频繁扩容会带来性能损耗。
- ✅
System.arraycopy
是最高效的,适合对性能敏感的场景 - ✅
ArrayList
虽然封装好,但不适合频繁插入,可考虑用LinkedList
- ❌ 不建议在循环中频繁使用数组扩容操作,应优先使用动态集合类如
ArrayList
6. 总结
虽然 Java 数组长度不可变,但我们可以通过创建新数组并复制内容的方式来“扩展”数组。常见的方法包括:
方法 | 适用场景 | 性能表现 | 灵活性 |
---|---|---|---|
Arrays.copyOf |
快速扩容 | 中等 | 高 |
ArrayList |
需频繁增删元素 | 一般 | 高 |
System.arraycopy |
对性能要求高的场景 | 高 | 中等 |
根据实际需求选择合适的方法,才能写出既简洁又高效的代码。数组扩容虽然简单,但背后的内存操作和性能考量不容忽视。
完整示例代码已托管在 GitHub 上,欢迎 clone 参考。