System.arraycopy是提升集合性能的关键,支撑ArrayList等底层数据搬运:扩容时整块迁移旧数组、删除时用左移避免循环、小size可跳过以优化性能。

System.arraycopy 本身不操作集合,但它直接支撑 ArrayList、Vector、ArrayDeque 等集合类的底层数据搬运——提升集合性能的关键,是让这些集合在扩容、删除、插入等操作中,用对 arraycopy 的调用时机和参数方式。
扩容时整块迁移,避免多次小拷贝
ArrayList.add 超出容量时,会 new 一个更大的数组,再把旧元素全部搬过去。这个“搬”就是 arraycopy:
- 目标数组必须提前分配好(如 new Object[newCapacity]),不能依赖 copyOf 封装——省去一次方法跳转和隐式判断
- 长度用旧数组实际 size,而非 capacity:System.arraycopy(oldElementData, 0, newElementData, 0, size),避免无效搬运
- size ≥ 256 时,JIT 自动启用 SIMD 指令;小 size(≤16)可考虑分支跳过 arraycopy,改用循环赋值
删除/移动元素时原地重排,不新建数组
ArrayList.remove(int index) 删除中间元素后,需要把后面的元素前移。传统 for 循环易出错且难优化,而 arraycopy 天然支持安全左移:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 例如删掉索引 3 的元素,后续 [4…size-1] 需前移一位:System.arraycopy(elementData, 4, elementData, 3, size - 4)
- src == dest 且 destPos
- 比手写 for 快 2–5 倍,且无边界错位风险;也不像 copyOf 那样多建一个数组
批量操作复用缓冲区,压低 GC 压力
集合的批量方法(如 removeAll、retainAll)内部常需临时数组暂存结果。若反复 new,会快速触发 Young GC:
立即学习“Java免费学习笔记(深入)”;
- 用 ThreadLocal
或对象池预分配 buffer,再用 arraycopy 写入有效段,实现零分配搬运 - 截取子集时,不调 Arrays.copyOfRange(它总 new 新数组),而是传入已有 dst 数组 + offset:System.arraycopy(src, from, dst, dstOffset, length)
- 对 byte[]、int[] 等基本类型数组,尤其适合——拷贝即位移,无引用语义干扰
类型与参数严格匹配,防止运行时崩
集合底层多用 Object[],但实际存的是 String、Integer 等。arraycopy 对类型校验极严:
- Object[] → String[] 不合法,会抛 ArrayStoreException;应确保 src 和 dest 组件类型兼容(如 String[] → Object[] 可行)
- 避免通过泛型擦除中转:List
toArray() 返回 T[],但擦除后可能是 Object[],再强转成子类型数组易破坏 JIT 内联 - length 必须 ≤ 源数组剩余长度,且 destPos + length ≤ dest.length —— 这些检查在入口一次性完成,错就立刻报,不静默失败

















