数组复制是影响算法正确性、性能和可维护性的关键操作,需根据场景选择arrays.copyof、clone()、system.arraycopy或循环:回溯需深拷贝防污染,动态结构依赖copyof扩容,多线程与函数式要求数据隔离。

数组复制在算法设计中不是“可有可无”的辅助操作,而是影响正确性、性能和可维护性的关键环节。直接赋值(a = b)只复制引用,会导致多个逻辑模块意外共享同一份数据——这在回溯、分治、动态规划等场景中极易引发隐蔽错误。
避免副作用:回溯与递归中的深拷贝需求
回溯算法常需在试探后“还原状态”,若仅传递数组引用,递归调用会相互污染。例如生成全排列时,每层递归修改当前路径数组,必须确保子调用不影响父层的原始状态。
- 推荐用
Arrays.copyOf(arr, arr.length)或arr.clone()创建独立副本,开销可控且语义清晰 - 避免在递归参数中传入原数组引用;如需截取片段,优先用
Arrays.copyOfRange(arr, from, to),不额外申请完整空间 - 对二维数组要注意:
clone()只是浅拷贝,外层数组新、内层数组仍共用;真正隔离需逐行复制或使用嵌套copyOf
支持动态结构:扩容与滑动窗口的底层实现
很多算法需动态调整数据容量,比如模拟 ArrayList 扩容、实现滑动窗口缓存、或构建稀疏数组索引。此时复制不是“备份”,而是结构演进的必要步骤。
-
Arrays.copyOf(original, newLength)是最常用方式:长度变大则补默认值(0、null),变小则截断,适合预分配场景 - 高性能场景(如高频 resize 的队列)倾向用
System.arraycopy:它由 JVM 本地实现,比循环快得多,且能精确控制源/目标偏移 - 滑动窗口中常需“挪动”一段数据,例如将窗口右移一位:
System.arraycopy(src, 1, dest, 0, windowSize),比新建数组更省内存
保证数据隔离:多线程与函数式风格下的安全传递
算法模块若被设计为无副作用(pure function),输入数组就不能被修改。此时复制是契约的一部分,而非冗余操作。
- 排序算法(如归并排序)的子过程必须基于副本操作,否则破坏原始输入,违反函数式接口约定
- 并发环境下,若多个线程分别处理同一数组的不同切片,应各自持有独立副本,避免加锁或竞态
- 用
Arrays.copyOfRange(arr, left, right)提取子数组,比手动 new + for 循环更简洁、不易越界
权衡选择:按场景选最匹配的方法
没有“万能复制法”,关键看你要什么:
- 要简单、语义明确、支持长度变更 → 选
Arrays.copyOf或copyOfRange - 要极致性能、已知目标数组存在、需指定起始位置 → 选
System.arraycopy - 要快速创建同类型同长度副本、代码极简 → 选
arr.clone()(注意引用类型元素仍共享) - 要完全控制每个元素(如做转换、过滤后再复制)→ 用 for 循环,灵活性最高











