Java数组扩容高性能核心是System.arraycopy:它作为JVM内置本地方法,直接内存块复制、支持重叠拷贝、JIT可向量化、仅一次边界校验;而for循环有下标检查开销,clone语义不清且多维异常。

Java 数组本身不可变长,所谓“手动实现高性能扩容”,核心是三件事:算好新容量、分配新数组、用最高效方式搬数据——System.arraycopy 就是这个“搬”的最优解。
为什么不用 for 循环或 clone
for 循环逐个赋值有明显开销:每次都要检查下标、调用 JVM 字节码、无法利用 CPU 批量指令。Object.clone() 对基本类型数组虽快,但语义不清晰,且对多维数组行为异常,容易埋坑。而 System.arraycopy 是 JVM 内置的本地方法,直接映射到内存块复制(类似 C 的 memcpy),支持重叠拷贝、JIT 可向量化、只做一次边界校验——这才是真正高性能的底层数组搬运工。
四步闭环:判断 → 分配 → 搬运 → 更新
扩容不是调一次 arraycopy 就结束,必须形成可控闭环:
- 先确认当前有效元素数(不是原数组 length,而是实际 size),避免把末尾默认值(如 0 或 null)也拷过去
- 计算新容量,推荐策略:
Math.max(size + 1, (int)(oldCap * 1.5)),兼顾空间利用率和扩容频次 - 用
new int[newCap](或对应类型)分配新数组,确保目标数组已存在且足够大 - 调用
System.arraycopy(src, 0, dest, 0, size),严格按有效长度搬运,完成数据迁移 - 最后更新引用(如
array = newArray)并同步维护 size 和 capacity 状态
典型代码模板(以 int[] 为例)
以下是最简、安全、可复用的手动扩容写法:
public static int[] expandArray(int[] oldArray, int newSize) {
if (oldArray == null) return new int[newSize];
if (newSize int[] newArray = new int[newSize];
int size = oldArray.length; // 若有独立 size 字段,此处应使用它
System.arraycopy(oldArray, 0, newArray, 0, size);
return newArray;
}
调用时:arr = expandArray(arr, (int)(arr.length * 1.5));
绕不开的细节提醒
几个高频出错点务必注意:
- 目标数组必须提前创建,arraycopy 不负责分配,传 null 直接抛 NullPointerException
- 拷贝长度必须是 当前有效元素个数,不是 oldArray.length(若数组有空洞),更不是 newArray.length
- 扩容后原数组对象未改变,所有其他引用仍指向旧数组——这不是 bug,是 Java 引用语义的本质
- 若用于环形结构(如自定义队列),不能直接 arraycopy 整个数组,需按 head/tail 分两段搬运,否则逻辑顺序错乱
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











