system.arraycopy真正快的关键在于使用条件:目标数组须预先分配且非null,拷贝长度建议≥16以规避jni开销,且必须同类型数组间搬运,否则无法触发jvm底层memmove或simd指令。

Java基本数据类型数组拷贝,真正快的关键不在“怎么写”,而在“什么时候用什么方式”——System.arraycopy 是唯一能触发 JVM 底层内存指令(如 memmove 或 SIMD)的 Java 原语,但它的优势只在合适条件下才完全释放。
优先选 System.arraycopy,但得满足三个前提
它快,是有条件的:
- 目标数组必须提前分配好:arraycopy 不负责新建数组,传入的 dest 必须是非 null、长度足够的已初始化数组;否则要先 new,反而增加 GC 压力
-
拷贝长度建议 ≥ 16:实测表明,length ≤ 16 时 JNI 调用开销常高于简单 for 循环;小数据可分支处理,比如:
if (len - 避免跨类型误用:int[] 拷到 long[] 会编译失败;byte[] 和 char[] 之间不兼容,运行时报 ArrayStoreException;基本类型间不自动转换
原地移位重排:用对方向,才能不丢数据
当 src == dest(同一数组),本质是内存块覆盖,顺序错了就覆盖未读数据:
- 左移(destPos :例如把索引 5~9 的 5 个元素前移 2 位 →
System.arraycopy(arr, 5, arr, 3, 5),JVM 自动正向执行,安全 -
右移(destPos > srcPos):例如把索引 0~4 的 5 个元素后移 3 位 →
System.arraycopy(arr, 0, arr, 3, 5),JVM 自动倒序执行,防止 arr[0] 覆盖 arr[3] 后,原 arr[3] 永久丢失 -
边界刚贴线也合法:如
System.arraycopy(arr, 7, arr, 6, 3)把 [7,8,9] 搬到 [6,7,8],destPos + length == 9,不越界,可放心用
别让 Arrays.copyOf 成为性能盲区
它看着简洁,但每次调用都隐含两步操作:
- 内部 new 一个目标数组(触发堆分配与可能的 GC)
- 再调用 System.arraycopy 完成搬运
- 若你已持有目标数组(比如循环复用缓冲区),直接 arraycopy 可省掉 30%~50% 时间(尤其高频小拷贝场景)
- 扩容时才真正需要 copyOf;固定长度复制,优先复用已有数组 + arraycopy
for 循环不是敌人,而是精准控制工具
它慢在通用性,但在特定场景反而更优:
- 需要条件过滤(如只拷非零值)、数值变换(如乘以系数)、或边界动态计算时,硬套 arraycopy 反而绕路
- 极小数组(≤ 4 元素)且无复用需求,for 循环指令少、无方法调用开销,实测更快
- 配合 JIT 编译,简单连续赋值循环可能被自动向量化(尤其是 JDK 17+)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











