在Java中,Queue
接口本身并不直接提供 addFirst()
方法。这个方法是 Deque
(双端队列)接口的一部分,而 LinkedList
类实现了 Deque
接口,因此它支持在队列的两端进行插入和删除操作,包括 addFirst()
方法。下面,我们将对 addFirst()
方法进行详细的剖析,并探讨它在 LinkedList
中的实现。
队列与双端队列
首先,需要明确的是,Queue
接口主要用于表示一个先进先出(FIFO)的队列,它支持的主要操作有 add(E e)
(在队尾添加元素)、offer(E e)
(尝试在队尾添加元素,如果队列满则返回false)、remove()
(移除并返回队头元素)、poll()
(尝试移除并返回队头元素,如果队列空则返回null)等。
而 Deque
(双端队列)接口扩展了 Queue
,它支持在队列的两端进行插入和删除操作。Deque
接口提供了 addFirst(E e)
、addLast(E e)
、offerFirst(E e)
、offerLast(E e)
、pollFirst()
、pollLast()
、peekFirst()
、peekLast()
等方法,允许在队列的前端和后端进行元素的添加和移除。
addFirst()
方法剖析
addFirst(E e)
方法是 Deque
接口的一部分,用于在双端队列的开头(即前端)添加一个元素。如果队列因为添加元素而超出了其容量限制(对于 LinkedList
来说,这通常不会发生,因为 LinkedList
是基于链表实现的,不受固定容量的限制),则抛出 IllegalStateException
(但请注意,LinkedList
实际上不会抛出此异常,因为它不受容量限制)。
在 LinkedList
的实现中,addFirst(E e)
方法通过以下步骤实现:
-
检查元素是否为null:虽然
LinkedList
允许null元素,但在某些应用中,检查null可能是一个好习惯。然而,addFirst()
方法本身并不直接检查null,这是由调用者负责的。 -
创建新的节点:为要添加的元素创建一个新的节点(Node)。在
LinkedList
中,每个节点都包含元素值、指向前一个节点的链接(prev)和指向下一个节点的链接(next)。 -
更新链接:
- 将新节点的
next
链接设置为当前队列的头部节点(即第一个元素所在的节点)。 - 如果队列是空的(即
first
和last
引用都为null),则将新节点的prev
链接也设置为null。 - 如果队列不为空,找到当前队列的头部节点的前一个节点(在
LinkedList
中,这通常是通过first.prev
访问的,但在添加第一个元素时,这将是null),并更新这个节点的next
链接以指向新节点。由于这是第一个元素,实际上没有前一个节点,但逻辑上可以这样理解。
- 将新节点的
-
更新队列的头部引用:将队列的
first
引用更新为新添加的节点。 -
增加队列的大小:增加
size
字段的值以反映队列中元素数量的增加。 -
(可选)更新队列的尾部引用:虽然
addFirst()
方法只影响队列的开头,但如果这是队列中的第一个元素(即队列之前为空),则还需要更新last
引用以指向新添加的节点。
示例
java复制代码
Deque<Integer> deque = new LinkedList<>(); | |
deque.addFirst(1); // 队列变为:[1] | |
deque.addFirst(0); // 队列变为:[0, 1] | |
System.out.println(deque); // 输出可能依赖于具体实现,但逻辑上应为:[0, 1] |
结论
addFirst()
方法是 Deque
接口的一部分,允许在双端队列的开头添加元素。在 LinkedList
的实现中,这个方法通过创建一个新节点,并更新队列的链接和大小来实现。由于 LinkedList
是基于链表实现的,因此这种方法的时间复杂度为O(1),即无论队列中有多少元素,添加操作的时间都是恒定的。