System.arraycopy实现数组合并:性能优化实战指南

作者:袖梨 2026-06-23
System.arraycopy合并数组需先创建目标数组、确认类型一致、校验源数组非null;两次拷贝参数须精准,小数组(≤16)手动赋值更优,对象数组仅复制引用。

System.arraycopy 合并数组本身不难,真正影响性能的是怎么用、在哪用、用之前做什么——它不是“开箱即用”的语法糖,而是直连内存的搬运指令,用对了快几倍,用错了可能比循环还慢。

合并前必须做三件事

很多人一上来就写两行 arraycopy,结果运行时报错或数据错乱。真正落地前,这三步不能跳:

  • 显式创建目标数组:长度必须是 arr1.length + arr2.length,少一个元素就抛 ArrayIndexOutOfBoundsException
  • 确认类型严格一致int[]long[] 不兼容,String[] 可以拷到 Object[],但反过来不行;编译不报错,运行时才炸
  • 校验源数组非 null:传入 null 直接抛 NullPointerException,建议合并前加空判断,而不是靠异常兜底

两次拷贝的参数必须严丝合缝

合并本质是两段内存搬运,第二段的起始位置决定拼接是否正确:

  • 第一段:System.arraycopy(arr1, 0, result, 0, arr1.length)
  • 第二段:System.arraycopy(arr2, 0, result, arr1.length, arr2.length) —— 这里的 arr1.length 是关键,不是 0,也不是 arr2.length
  • 常见错误:把第二段的 destPos 写成 0,导致 arr2 覆盖 arr1 的数据;或写成 result.length - arr2.length,在 arr1 为空时出错

小数组别硬套 arraycopy

它快是有条件的。实测表明,当拷贝长度 ≤ 16 时,JNI 调用开销常超过简单赋值,反而更慢:

  • 长度 ≤ 4:直接用 result[0] = a[0]; result[1] = a[1]; ... 更稳更快
  • 长度 5–16:可分支判断,走手动赋值;或统一用 arraycopy,但别指望收益
  • 长度 ≥ 32:arraycopy 优势开始明显,越大越显著(百万级数组可快 3–5 倍)

对象数组合并要注意引用语义

System.arraycopy 对对象数组只复制引用,不深拷贝:

  • 合并后,result[i] 和原 arr1[i] 指向同一个对象实例
  • 后续修改该对象的字段,所有引用处同步可见——这是特性,不是 bug
  • 若需深拷贝,应在 arraycopy 后遍历调用 clone()(要求实现 Cloneable),或用序列化工具重建

相关文章

精彩推荐