System.arraycopy本身不扩容,真正的高性能扩容需嵌入“判断→分配→搬运→更新”闭环;扩容触发条件是size == array.length,新容量推荐1.5倍增长并设最小增量,搬运长度必须为size,引用与状态须同步更新,中间插入/删除也依赖arraycopy局部迁移。

System.arraycopy 本身不扩容,只高效搬运数据;真正的高性能扩容,是把它嵌入“判断→分配→搬运→更新”四步闭环中,关键不在复制本身,而在如何让每次搬运都精准、必要、无冗余。
扩容触发必须基于 size 而非 length
数组长度(length)只是容量上限,真正决定是否该扩的是已存元素数(size)。仅当 size == array.length 时才触发扩容,避免提前分配浪费内存,也防止插入失败。若用 length 判断,会误判空数组或未满数组需扩。
新容量要兼顾平滑性与内存效率
固定 ×2 容易造成中等规模数据的内存浪费;推荐采用 1.5 倍增长(即 oldCap + (oldCap >> 1)),并设最小增量保障:
- newCapacity = Math.max(size + 1, (int)(oldCapacity * 1.5))
- 即使当前 size 是 1,新容量也不能小于 2,防止单次 add 就触发下一轮扩容
- 初始容量建议设为 8 或 16,避开小数组高频抖动
搬运必须严格限定有效长度
System.arraycopy 的第五个参数(length)必须是 当前有效元素个数 size,不是原数组 length,更不是新数组 newLength:
- 错写成 array.length:若数组有空洞(如删除后未压缩),会把默认值(0 / null)一并拷过去,污染逻辑
- 错写成 newLength:目标数组末尾被默认值填充,后续读取可能出错
- 正确写法:System.arraycopy(oldData, 0, newData, 0, size)
引用与状态必须同步更新
搬运完不更新引用,等于白干。两处必须同时改:
- 将底层数组引用指向新数组:data = newData
- 更新容量认知:若类中维护 capacity 字段,需同步赋值;更简洁做法是直接用 data.length 表示当前容量,省去冗余字段和不一致风险
中间插入/删除也要靠 arraycopy 局部迁移
高性能不止于尾部追加。在 index 插入或删除时,仍可用一次 arraycopy 完成局部搬移:
- 插入:将 data[index .. size−1] 整体后移到 index+1 起始位置,再填新值
- 删除:将 data[index+1 .. size−1] 整体前移到 index 起始位置,最后 size−−
- 两次操作都只调用一次 arraycopy,长度可控,不涉及全量重建
不复杂但容易忽略


















