Collection - Queue 源码解析

102 阅读2分钟

Queue

Queue接口继承自Collection接口,扩展方法有6个,一组是抛出异常的实现,另外一组是返回值的实现(没有则返回null)。

抛异常返回值
插入add(e)offer(E e)
删除remove()poll()
查询element()peek()

Deque(双向队列)

Deque 接口继承之 Queue,扩展方法有12个

头部操作尾部操作
抛异常返回值抛异常返回值
插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
删除removeFirst()pollFirst()removeLast()pollLast()
查询getFirst()peekFirst()getLast()peekLast()

ArrayDeque

ArrayDeque 一种双端队列实现。它继承自 AbstractCollection 类并实现了 Deque 接口,提供了高效的插入和删除操作

ArrayDeque和LinkedList是Deque的两个通用实现,官方更推荐使用AarryDeque用作栈和队列

数据结构

ArrayDeque 内部使用一个循环数组作为底层数据结构。数组的长度会根据实际元素数量进行动态调整,以实现高效的插入和删除操作。

首先,我们来看一下 ArrayDeque 的主要成员变量:

    //存储元素的数组
    transient Object[] elements; 
    //指向队列头部元素的索引
    transient int head;
    //指向队列尾部元素的索引
    transient int tail;

head 和 tail 变量的值会根据插入和删除操作进行调整,以维护队列的双端特性。

image

扩容机制

当队列的元素数量达到了数组长度时,会触发扩容操作。下面是 ArrayDeque 的扩容过程:

  1. 创建一个新的数组,长度为原数组的两倍,并将原数组中的元素按顺序复制到新数组中。
  2. 调整新数组的 head 和 tail 索引,使其指向正确的位置。
//ArrayDeque 默认容量为 16
//当 last == head 时,进行扩容一倍

private void doubleCapacity() {
    assert head == tail;
    int p = head;
    int n = elements.length;
    int r = n - p; // number of elements to the right of p
    int newCapacity = n << 1; // 容量扩容一倍
    if (newCapacity < 0)
        throw new IllegalStateException("Sorry, deque too big");
    Object[] a = new Object[newCapacity];
    
    // 拷贝到新数组
    System.arraycopy(elements, p, a, 0, r);
    System.arraycopy(elements, 0, a, r, p);
    elements = a;
    head = 0;
    tail = n;
}