文章目录
- 概述
 - ArrayDeque基础知识
 - ArrayDeque内部结构
 - ArrayDeque的构造方法
 - ArrayDeque的扩容操作
 
- ArrayDeque常用方法
 - 将ArrayDeque作为双端队列使用时
 - public void addFirst(E e)
 - public void addLast(E e)
 - public boolean offerFirst(E e)
 - public boolean offerLast(E e)
 - public E pollFirst()
 - public E pollLast()
 - public E removeFirst()
 - public E removeLast()
 - public E getFirst()
 - public E getLast()
 - public E peekFirst()
 - public E peekLast()
 
- 将ArrayDeque作为队列使用时
 - public boolean add(E e)
 - public boolean offer(E e)
 - public E remove()
 - public E poll()
 - public E element()
 - public E peek()
 
- 将ArrayDeque作为栈使用时
 - public void push(E e)
 - public E pop()
 
- 其他方法
 - public int size()
 - public boolean isEmpty()
 - public boolean contains(Object o)
 - public void clear()
 - public Object[] toArray()
 - public ArrayDeque<E> clone()
 
概述
java.util.ArrayDeque是Queue和Deque接口的基础集合。它的继承实现关系如下:
 
public class ArrayDeque<E> extends AbstractCollection<E>
        implements Deque<E>, Cloneable, Serializable
 
ArrayDeque继承至AbstractCollection并实现了Deque, Cloneable, Serializable接口,支持可复制以及序列化操作。
ArrayDeque集合是一个基于可循环双指针数组(可扩容)结构实现的双端队列,它既有队列、双端队列的特点,又有栈结构的特点,可用来代替Stack集合进行栈结构的操作。
ArrayDeque基础知识
ArrayDeque内部结构
ArrayDeque的内部结构主要是一个数组,该数组结构是一种可循环使用的数组结构,称为循环数组。
循环数组是一个固定大小的数组,并定义了一个动态的有效数据范围(有限范围小于数组固定长度),只有在有效范围内的数据对象才能被读写,且该有效范围不受数组的头尾限制。
实现中,循环数组定义为elements,并使用名为head、tail的两个属性表示动态的有效数据:
 
- head属性用于标识下一次进行移除操作的数据对象索引位(队列头部索引为);
 - tail属性用于标识下一次进行添加操作的数据对象索引位(队列尾部索引为)。
 
当tail属性指向数组的所有一个索引位并进行下一次添加操作时,数组不一定进行扩容操作,而是:tail属性重新从当前数组的0号索引位开始,循环利用有限数据范围外的数组索引位存储新的数据对象。
ArrayDeque的构造方法
1. 构造一个空的ArrayDeque,初始容量为16。
    public ArrayDeque() {
        elements = new Object[16];
    }
 
2. 构造一个空的ArrayDeque,初始容量为指定大小numElements。
public ArrayDeque(int numElements) {
        allocateElements(numElements);
    }
    private void allocateElements(int numElements) {
        elements = new Object[calculateSize(numElements)];
    }
 
3. 构造一个包含指定集合元素的ArrayDeque
    public ArrayDeque(Collection<? extends E> c) {
        allocateElements(c.size());
        addAll(c);
    }
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }
 
ArrayDeque的扩容操作
ArrayDeque的扩容操作包括以下两步:
- 根据当前容量大小计算新的容量。
当扩容前的容量较小时,按照扩容前容量值的1倍计算增量值;当扩容前的容量较大时(超过64),按照扩容前容量值的50%计算增量值。 - 按照计算得到的扩容增量值使用System.arraycopy方法进行扩容。
 
    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;
    }
 
ArrayDeque常用方法
将ArrayDeque作为双端队列使用时
public void addFirst(E e)
在此deque头部插入指定的元素。
    public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }
 
public void addLast(E e)
在此deque尾部插入指定的元素。
    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ((tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }
 
public boolean offerFirst(E e)
在此deque头部插入指定的元素。
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
 
public boolean offerLast(E e)
在此deque尾部插入指定的元素。
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
 
public E pollFirst()
检索并删除此deque的第一个元素,如果此deque为空,则返回 null 。
    public E pollFirst() {
        int h = head;
        @SuppressWarnings("unchecked")
        E result = (E) elements[h];
        // Element is null if deque empty
        if (result == null)
            return null;
        elements[h] = null;     // Must null out slot
        head = (h + 1) & (elements.length - 1);
        return result;
    }
 
public E pollLast()
检索并删除此deque的最后一个元素,如果此deque为空,则返回 null 。
    public E pollLast() {
        int t = (tail - 1) & (elements.length - 1);
        @SuppressWarnings("unchecked")
        E result = (E) elements[t];
        if (result == null)
            return null;
        elements[t] = null;
        tail = t;
        return result;
    }
 
public E removeFirst()
检索并删除此deque的第一个元素。 此方法与pollFirst不同之处在于,如果此deque为空,它将抛出异常。
    public E removeFirst() {
        E x = pollFirst();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }
 
public E removeLast()
检索并删除此deque的最后一个元素。 此方法与pollLast不同之处在于,如果此deque为空,它将抛出异常。
    public E removeLast() {
        E x = pollLast();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }
 
public E getFirst()
检索但不删除此deque的第一个元素,如果此deque为空,则抛出异常。
    public E getFirst() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[head];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }
 
public E getLast()
检索但不删除此deque的最后一个元素,如果此deque为空,则抛出异常。
    public E getLast() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[(tail - 1) & (elements.length - 1)];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }
 
public E peekFirst()
检索但不删除此deque的第一个元素,如果此deque为空,则返回 null 。
    public E peekFirst() {
        // elements[head] is null if deque empty
        return (E) elements[head];
    }
 
public E peekLast()
检索但不删除此deque的最后一个元素,如果此deque为空,则返回 null 。
    public E peekLast() {
        return (E) elements[(tail - 1) & (elements.length - 1)];
    }
 
将ArrayDeque作为队列使用时
public boolean add(E e)
在此deque的末尾插入指定的元素。
    public boolean add(E e) {
        addLast(e);
        return true;
    }
 
public boolean offer(E e)
在此deque的末尾插入指定的元素。
    public boolean offer(E e) {
        return offerLast(e);
    }
 
public E remove()
检索并删除由此deque的头部元素。 如果此deque为空,它将抛出异常。
    public E remove() {
        return removeFirst();
    }
 
public E poll()
检索并删除由此deque的头部元素。 如果此deque为空,返回null。
    public E poll() {
        return pollFirst();
    }
 
public E element()
检索但不删除由此deque的头部元素。 如果此deque为空,它将抛出异常。
    public E element() {
        return getFirst();
    }
 
public E peek()
检索但不删除由此deque的头部元素。 如果此deque为空,返回null。
    public E peek() {
        return peekFirst();
    }
 
将ArrayDeque作为栈使用时
public void push(E e)
入栈
    public void push(E e) {
        addFirst(e);
    }
 
public E pop()
出栈
    public E pop() {
        return removeFirst();
    }
 
其他方法
public int size()
返回此deque中的元素数。
    public int size() {
        return (tail - head) & (elements.length - 1);
    }
 
public boolean isEmpty()
判断此deque是否为空。
    public boolean isEmpty() {
        return head == tail;
    }
 
public boolean contains(Object o)
如果此deque包含指定的元素,则返回true 。
    public boolean contains(Object o) {
        if (o == null)
            return false;
        int mask = elements.length - 1;
        int i = head;
        Object x;
        while ((x = elements[i]) != null) {
            if (o.equals(x))
                return true;
            i = (i + 1) & mask;
        }
        return false;
    }
 
public void clear()
清空
    public void clear() {
        int h = head;
        int t = tail;
        if (h != t) { // clear all cells
            head = tail = 0;
            int i = h;
            int mask = elements.length - 1;
            do {
                elements[i] = null;
                i = (i + 1) & mask;
            } while (i != t);
        }
    }
 
public Object[] toArray()
返回一个包含此deque中所有元素的数组(从第一个到最后一个元素)。
    public Object[] toArray() {
        return copyElements(new Object[size()]);
    }
 
public ArrayDeque clone()
返回此deque的副本。
    public ArrayDeque<E> clone() {
        try {
            @SuppressWarnings("unchecked")
            ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
            result.elements = Arrays.copyOf(elements, elements.length);
            return result;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
                


















