1. 概述

本文将深入讲解 Java 中的 ArrayDeque 类——它是 Deque 接口的一个实现。

ArrayDeque(全称 "Array Double Ended Queue",读作 "ArrayDeck")是一种特殊的可扩展数组,允许我们在两端高效地添加或删除元素

ArrayDeque 实现既可作为 栈(Stack,后进先出) 使用,也可作为 队列(Queue,先进先出) 使用。

2. API 快速一览

对于每种操作,我们都有两种方法可选:

  • 抛异常组:操作失败时抛出异常
  • 状态返回组:操作失败时返回状态或特殊值
操作 状态返回方法 抛异常方法
头部插入 offerFirst(e) addFirst(e)
头部移除 pollFirst() removeFirst()
头部获取 peekFirst() getFirst()
尾部插入 offerLast(e) addLast(e)
尾部移除 pollLast() removeLast()
尾部获取 peekLast() getLast()

3. 方法使用实践

下面通过几个简单示例展示 ArrayDeque 的实际用法。

3.1 用作栈(Stack)

先看如何将 ArrayDeque 当作栈使用,压入元素:

@Test
public void whenPush_addsAtFirst() {
    Deque<String> stack = new ArrayDeque<>();
    stack.push("first");
    stack.push("second");
 
    assertEquals("second", stack.getFirst());
}

再演示弹出元素的操作:

@Test
public void whenPop_removesLast() {
    Deque<String> stack = new ArrayDeque<>();
    stack.push("first");
    stack.push("second");
 
    assertEquals("second", stack.pop());
}

⚠️ 注意:当栈为空时,pop() 方法会抛出 NoSuchElementException

3.2 用作队列(Queue)

现在展示如何将 ArrayDeque 当作普通队列使用,添加元素:

@Test
public void whenOffer_addsAtLast() {
    Deque<String> queue = new ArrayDeque<>();
    queue.offer("first");
    queue.offer("second");
 
    assertEquals("second", queue.getLast());
}

以及从队列中取出元素:

@Test
public void whenPoll_removesFirst() {
    Deque<String> queue = new ArrayDeque<>();
    queue.offer("first");
    queue.offer("second");
 
    assertEquals("first", queue.poll());
}

✅ 当队列为空时,poll() 方法会返回 null 而非抛出异常。

4. ArrayDeque 实现原理

ArrayDeque 内部结构

底层实现上,ArrayDeque 由一个动态数组支撑,当数组填满时会自动扩容(容量翻倍)

初始容量为 16,通过维护 头指针(head)尾指针(tail) 实现双端队列功能。下面通过图解说明核心逻辑:

4.1 作为栈的实现

下图展示了 ArrayDeque 作为栈时的操作流程:

  1. stack.push("first")
  2. stack.push("second")
  3. stack.pop()

ArrayDeque 作为栈的操作

关键点:

  • push() 操作将元素压入栈顶,并移动头指针指向新元素
  • pop() 操作将当前头位置元素置为 null(便于 GC),然后头指针后移一位

4.2 作为队列的实现

ArrayDeque 作为队列的操作

核心机制:

  • offer() 操作移动尾指针
  • poll() 操作将头位置元素置为 null(触发 GC),然后移动头指针

4.3 重要特性总结

关于 ArrayDeque 的关键注意事项:

  • 非线程安全:多线程环境下需手动同步
  • 拒绝 null 元素:添加 null 会抛出 NullPointerException
  • 性能优势:比同步的 Stack 快得多
  • 队列性能:因内存局部性更好,比 LinkedList 更快
  • ⏱️ 时间复杂度:大多数操作均摊时间复杂度为 O(1)
  • ⚠️ 迭代器特性:返回的 Iterator 是 fail-fast 的
  • 🔄 自动扩容:当添加元素时头尾指针相遇,数组容量自动翻倍

5. 总结

本文通过代码示例和图解,详细展示了 ArrayDeque 的核心用法和实现原理。

所有示例代码可在 GitHub 项目 中获取(基于 Maven 构建,可直接导入运行)。


原始标题:Introduction to the Java ArrayDeque | Baeldung