arraydeque的clone方法执行逻辑拷贝而非物理复制,创建新数组并按逻辑顺序复制有效元素,重置head=0、tail=size,确保克隆体为紧凑线性结构且语义等价。

ArrayDeque 的 clone 方法并不直接拷贝环形数组的内部结构,而是创建一个新数组并复制有效元素,不保留原始的环形布局。
clone 方法实际行为:浅拷贝 + 重排成线性顺序
ArrayDeque 的 clone() 方法返回的是一个新的 ArrayDeque 实例,它:
- 分配一个与原队列
size()相同长度的新数组(不是原底层数组的长度) - 将原队列中从
head开始、按逻辑顺序遍历的全部元素,依次复制到新数组的索引0到size-1 - 重置新实例的
head = 0、tail = size,即新队列总是以“紧凑线性”方式存储 - 不复制原数组的空闲位置或环形偏移,也不共享底层数组
这意味着:即使原 ArrayDeque 底层数组已发生多次扩容/旋转(如 head=5, tail=2, 数组长度=16),clone 出的对象内部数组一定是 head=0、tail=n、元素连续存放的。
为什么不是简单复制底层数组?
直接复制整个底层数组(如 Arrays.copyOf(elements, elements.length))会带来问题:
- 浪费空间:包含大量未使用的
null占位项 - 破坏语义:克隆后
size()仍正确,但elements中混杂有效/无效数据,易引发误用 - 违反封装:暴露内部环形实现细节,违背“逻辑容器”抽象
因此 JDK 选择语义一致的“逻辑拷贝”,确保克隆体行为与新建队列完全等价。
源码关键逻辑(JDK 17+)
简化后的核心步骤如下:
public ArrayDeque<e> clone() {
try {
ArrayDeque<e> result = (ArrayDeque<e>) super.clone();
result.elements = new Object[result.size()]; // 新建刚好够用的数组
final int size = this.size();
if (size > 0) {
final Object[] src = this.elements;
final int srcSize = src.length;
final int head = this.head;
// 将 [head ... end] 和 [0 ... tail-1] 两段拼接写入 result.elements[0...size-1]
if (head </e></e></e>实际使用注意事项
- 克隆后两个队列完全独立:修改任一队列的元素或执行 add/remove,不会影响另一个
- 元素本身是浅拷贝:若元素为可变对象(如
ArrayList),需自行深拷贝其内容 - 性能上:时间复杂度 O(n),空间额外开销 O(n),但避免了冗余容量
- 若需保留原始内存布局(极少见),应避免使用 clone,改用序列化或手动重建
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











