system.arraycopy不支持原地重叠移动的自动安全处理,必须人工拆分步骤避覆盖;左移k位需三步:暂存前k个、后n−k前移、暂存数据贴末尾。

System.arraycopy() 本身不支持“原地左右移动”时的重叠区域自动安全处理——它只是底层内存块复制,**重叠时行为取决于方向和参数,必须人工保证逻辑正确性**。所谓“原地移动”,本质是用 arraycopy 模拟循环移位(如左移 k 位、右移 k 位),关键在于**拆分复制步骤,避开覆盖风险**。
为什么 arraycopy 在重叠时可能出错?
当源数组和目标数组是同一个对象,且源范围与目标范围有交集时:
• 若 从左往右复制(srcPos
• 若 从右往左复制(srcPos > destPos),前段数据可能被提前覆盖。arraycopy 不做重叠检测,直接按字节顺序拷贝,结果不可靠。
实现左移 k 位(循环左移)
目标:将数组 a[0..n-1] 循环左移 k 位 → a[k%n], a[k%n+1], ..., a[k%n-1]
安全做法:分三步,用两次 arraycopy + 一次反转(或三次拷贝)
- 先复制前 k 个元素到临时空间(或复用数组尾部)
- 将后 n−k 个元素前移 k 位(srcPos = k, destPos = 0, length = n−k)→ 此时
srcPos > destPos,安全 - 再把暂存的前 k 个元素贴到末尾(srcPos = 0, destPos = n−k, length = k)→ 此时
srcPos ,也安全
示例(左移 2):
原数组:[1,2,3,4,5] → 暂存 [1,2] → 前移后段:[3,4,5,5,5] → 填回:[3,4,5,1,2]
实现右移 k 位(循环右移)
等价于循环左移 n−k 位;或直接分步:
• 暂存后 k 个元素
• 将前 n−k 个元素后移 k 位(srcPos = 0, destPos = k, length = n−k)→ srcPos ,安全<br>
• 把暂存内容填到开头(srcPos = 0, destPos = 0)→ 无重叠,安全
更简洁:用三次反转代替拷贝(无需临时空间)
循环右移 k 位可转化为:
• 反转 [0, n−k−1]
• 反转 [n−k, n−1]
• 反转整个 [0, n−1]
每步反转都可用 arraycopy 配合临时变量逐对交换,完全规避重叠问题;或者直接写 for 循环交换,更直观。
不复杂但容易忽略:arraycopy 的重叠安全与否,只取决于你调用时的 srcPos/destPos 相对位置和 length。只要拆开操作、控制好方向,就能在不分配额外数组的情况下完成原地移位。











