system.arraycopy仅高效搬运数据,不扩容;动态扩容需封装容量判断、新数组分配、数据搬运、引用更新四步闭环,并独立维护size与length。

System.arraycopy 本身不扩容,只负责高效搬运数据;真正的动态扩容,是把“容量判断→新数组分配→数据搬运→引用更新”这四步闭环封装进类中,并配合合理的容量管理策略,让使用者感知不到底层变化。
容量与 size 必须分开维护
数组的 length 是物理容量,size 才是当前已存元素个数。只靠 length 判断是否满员会出错——比如你删掉几个元素后,length 没变但实际可用空间多了。必须独立维护一个 size 字段:
- 所有 add()、set() 前检查 if (size >= data.length),触发扩容
- remove() 或 clear() 后只减 size,不缩容(除非明确需要)
- get(int i) 要校验 i
扩容计算要兼顾平滑与底线
不能简单写成 newLength = oldLength * 2,小数组容易浪费,大数组可能溢出。推荐用带下限保障的 1.5 倍策略:
- newCapacity = Math.max(size + 1, (int)(oldCapacity * 1.5))
- 初始容量建议设为 8 或 16,避开前几次频繁扩容
- 如果调用方提前知道大概规模,提供 ensureCapacity(int min) 方法预分配,减少临界点抖动
搬运时只拷贝有效数据
System.arraycopy 的 length 参数必须传 size,不是 newCapacity,也不是 oldCapacity:
- Object[] newData = new Object[newCapacity];
- System.arraycopy(data, 0, newData, 0, size); // 关键:只搬 size 个
- data = newData; // 引用切换,旧数组等待 GC
传错 length 会导致末尾填入默认值(如 null),后续 get() 可能返回意外 null,逻辑被静默污染。
插入/删除也要靠 arraycopy 局部搬移
动态数组不止支持尾部追加。在 index 处插入或删除,同样用 arraycopy 高效完成局部迁移:
- 插入:先将 data[index ... size-1] 搬到 data[index+1 ... size],再赋值 data[index] = value
- 删除:将 data[index+1 ... size-1] 搬到 data[index ... size-2],然后 size--
- 两次操作都只调一次 arraycopy,长度可控,不重建全量











