在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),即无论队列中有多少元素,添加操作的时间都是恒定的。