【Java基础】ArrayDeque

1. 定义

ArrayDeque:基于数组的双端队列

2. 特点
  1. 用作栈时,比Stack快;用作队列时,比LinkedList快。
  2. ArrayDeque的大多数操作运行时的时间分摊下来都是常数时间(O(1))。除了remove,removeFirstOccurrence,removeLastOccurrence,contains,iterator.remove() and the bulk operations,这些操作的时间复杂度是O(n)。
  3. 非线程安全
3. 基本功能
属性:
transient Object[] elements;
//用于进行remove()或pop()操作时的索引;当队列为空时,head==tail(任意值)。
transient int head;
//下一个元素被添加到的位置,用于进行addLast(E),add(E),push(E)
transient int tail;
//最小初始化容量(必须是2的指数)
private static final int MIN_INITIAL_CAPACITY = 8;
方法:
  1. allocateElements(int numElements) 把参数转成2的指数,然后new Object数组。
private void allocateElements(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY;
        // Find the best power of two to hold elements.
        // Tests "<=" because arrays aren't kept full.
        if (numElements >= initialCapacity) {
            initialCapacity = numElements;
            initialCapacity |= (initialCapacity >>>  1);
            initialCapacity |= (initialCapacity >>>  2);
            initialCapacity |= (initialCapacity >>>  4);
            initialCapacity |= (initialCapacity >>>  8);
            initialCapacity |= (initialCapacity >>> 16);
            initialCapacity++;

            if (initialCapacity < 0)   // Too many elements, must back off
                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
        }
        elements = new Object[initialCapacity];
    }
  1. doubleCapacity()
    把deque的数组容量扩充为2倍大。只有当满了的时候才执行,也就是head和tail变得相等时。
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];
        //先把从p到最后的部分copy至新数组中,再把前半部分copy至新数组。
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = a;
        head = 0;
        tail = n;
    }
  1. copyElements(T[] a) 把数组拷贝到另一个特定的数组中
  2. 构造函数
    public ArrayDeque()
    public ArrayDeque(int numElements)
    public ArrayDeque(Collection<? extends E> c)
  3. addFirst(E e)
    在双端队列的前端插入元素
public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        //如果head==tail,就进行扩容
        if (head == tail)
            doubleCapacity();
    }
  1. addLast(E e)
public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        //当tail==head时,扩容,其中,tail=tail+1,再对tail进行取余
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }
  1. offerFirst(E e) 返回true/false
public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
  1. offerLast(E e)
public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
  1. removeFirst()
public E removeFirst() {
        E x = pollFirst();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }
  1. removeLast()
public E removeLast() {
        E x = pollLast();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }
  1. pollFirst()
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指针
        head = (h + 1) & (elements.length - 1);
        return result;
    }
  1. pollLast()
public E pollLast() {
		//获得尾部元素的index,tail-1是因为tail指向下一个插入元素的位置
        int t = (tail - 1) & (elements.length - 1);
        @SuppressWarnings("unchecked")
        E result = (E) elements[t];
        if (result == null)
            return null;
        elements[t] = null;
        //把tail向前移
        tail = t;
        return result;
    }
  1. getFirst()
public E getFirst() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[head];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }
  1. getLast()
public E getLast() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[(tail - 1) & (elements.length - 1)];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }
  1. peekFirst()
public E peekFirst() {
        // elements[head] is null if deque empty
        return (E) elements[head];
    }
  1. peekLast()
public E peekLast() {
        return (E) elements[(tail - 1) & (elements.length - 1)];
    }
  1. removeFirstOccurrence(Object o)
    设e.removeFirstOccurrence(o),则移除第一个o.equals(e)的元素(从head到tail遍历deque)。如果deque中不包含这个元素,deque不变。如果包含,return true。
public boolean removeFirstOccurrence(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)) {
                delete(i);
                return true;
            }
            i = (i + 1) & mask;
        }
        return false;
    }
  1. add(E e); offer(E e); remove(); poll(); peek(); push(E e); pop()
    其中,在头部进行操作的有:remove(); poll(); peek(); push(E e); pop();
    在尾部进行操作的有:add(E e); offer(E e);
  2. delete(int i)
    移除指定位置的元素,并调整head和tail。将要删除位置后边的元素全部往前挪。
private boolean delete(int i) {
        checkInvariants();
        final Object[] elements = this.elements;
        final int mask = elements.length - 1;
        final int h = head;
        final int t = tail;
        final int front = (i - h) & mask;
        final int back  = (t - i) & mask;

        // Invariant: head <= i < tail mod circularity
        if (front >= ((t - h) & mask))
            throw new ConcurrentModificationException();

        // Optimize for least element motion
        if (front < back) {
            if (h <= i) {
                System.arraycopy(elements, h, elements, h + 1, front);
            } else { // Wrap around
                System.arraycopy(elements, 0, elements, 1, i);
                elements[0] = elements[mask];
                System.arraycopy(elements, h, elements, h + 1, mask - h);
            }
            elements[h] = null;
            head = (h + 1) & mask;
            return false;
        } else {
            if (i < t) { // Copy the null tail as well
                System.arraycopy(elements, i + 1, elements, i, back);
                tail = t - 1;
            } else { // Wrap around
                System.arraycopy(elements, i + 1, elements, i, mask - i);
                elements[mask] = elements[0];
                System.arraycopy(elements, 1, elements, 0, t);
                tail = (t - 1) & mask;
            }
            return true;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值