在数据结构方面,LinkedList不仅实现了与ArrayList相同的List接口,还实现了Deque接口。今天的ArrayDeque是在Deque接口上实现的动态数组。
Deque接口表示一个双端队列,允许在队列的两端进行操作。因此,它可以实现队列行为和堆栈行为。
一、ArrayDeque的特点
描述ArrayDeque的特点:
ArrayDeque是一个基于动态数组的双端Deque队列,它内部封装了容量扩展和数据传输的逻辑;
ArrayDeque的阵列容量保证为2的整数次方;
ArrayDeque不是线程安全的;
ArrayDeque不支持空元素;
尽管ArrayDeque有可能通过进入堆栈和队列来触发容量扩展,但从平均共享分析的角度来看,它仍然是O(1)时间复杂性;
ArrayDeque迭代器还具有快速失败机制。ArrayDeque通过头指针和尾指针的位置和元素检查并发修改,而不是使用类似于ArrayList的modCount来检查并发修改。此方法可能无法保证可以检测到所有并发修改。例如,无法检查是否先删除尾部元素,然后立即添加。
二、ArrayDeque和LinkedList之间的区别是什么
1.数据结构:在数据结构方面,ArrayDeque和LinkedList都实现了JavaDeque双终端队列接口。然而,ArrayDeque没有实现JavaList接口,因此它不会根据索引位置进行操作;
2.线程安全:ArrayDeque和LinkedList不考虑线程同步,不保证线程安全;
.底层实现:在底层实现中,ArrayDeque基于动态数组,而LinkedList基于双向链表。
在遍历速度方面:ArrayDeque是一个连续的内存空间,基于局部性原则可以更好地命中CPU缓存线,而LinkedList是一个对缓存线不友好的离散内存空间;
就操作速度而言,ArrayDeque和LinkedList的堆栈和队列行为都是O(1)时间复杂度。ArrayDeque的堆栈和队列入口可能会触发容量扩展,但从共享分析的角度来看,它仍然是O(1)时间复杂性;
在额外的内存消耗方面:ArrayDeque在数组的头指针和尾指针之外有空闲空间,而LinkedList向节点添加了一个前置指针和后续指针。
三、如何使用数组实现堆栈和队列
我们知道堆栈和队列是具有“操作约束”的线性表:堆栈是LIFO,限制在表一端的入站和出站。队列是FIFO,限制在表的一端进入,另一端离开。堆栈和队列可以通过数组或链表实现:
数组:当用数组实现时,它们被称为顺序堆栈和顺序队列;
链表:用链表实现时,称为链式堆栈和链式队列。
现在我们可以回答这个问题了。互联网上也有材料称ArrayDeque没有容量限制。最糟糕的是,代码注释还说,“数组请求没有容量限制”。显然情况并非如此。首先,阵列的容量显示为由虚拟机固定,不可能有无限容量。其次,从doubleCapacity()函数中,我们可以看到最大容量值为2^0(高阶为,低阶为0)。如果超过此数字,则在扩展doubleCapacity()时将引发异常。
四、为什么ArrayList不适合实现队列?
在文章中,我们提到了LinkedList的多方面生命,它既是列表的链接列表、队列的连接队列,也是“堆栈”的链接堆栈。它具有全面的功能。相反,ArrayList只是一个实现List的顺序表。为什么?
这是因为当同时在数组上实现List和Queue时,无法平衡这两种行为之间的性能矛盾。具体来说,ArrayList不允许底层数据中存在漏洞。所有有效数据将被“压缩”到基础数组的顶部。因此,使用ArrayList开发堆栈结构可能是合适的。您可以在数组末尾操纵数据。但是,使用ArrayList来开发队列是不合适的,因为在阵列的开头进入或离开队列需要移动数据