ArrayDeque源码解析

ArrayDeque

  • 实现了Deque接口,
  • 非线程安全
  • 禁止使用空元素。
  • 当用作堆栈时,此类可能比Stack快,并且当用作队列时比LinkedList更快。

类的字段中包含 初始容量、头尾指针,以数组为底层数据结构

    transient Object[] elements; 
    transient int head;
    transient int tail;
    private static final int MIN_INITIAL_CAPACITY = 8;

构造器

 // 默认构造器 初始容量为16
  public ArrayDeque() {
        elements = new Object[16];
    }
   // 创建一个ArrayDeque 指定容量大小为 numElements 
    public ArrayDeque(int numElements) {
        allocateElements(numElements);
    }
    // 创建一个 ArrayDeque,初始数据为 collection c的所有值
    public ArrayDeque(Collection<? extends E> c) {
        allocateElements(c.size());
        addAll(c);
    }

分配具体容量和扩容成两倍容量方法

private void allocateElements(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY; // 初始容量为8
        // 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];
    }
    
       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;
    }

 

添加方法

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) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }

 

值得注意的是 ArrayDeque的 push和pop 分别后台用的是 addFirst 和 removeFirst,也就是你直接把ArrayDeque当成栈用

public void push(E e) {
        addFirst(e);
    }
public E pop() {
        return removeFirst();
    }
 public E peek() {
        return peekFirst();
    }

值得注意的是 ArrayDeque的offer,poll可以当成队列用

  public boolean offer(E e) {
        return offerLast(e);
    }
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
  public E poll() {
        return pollFirst();
    }
    public E remove() {
        return removeFirst();
    }

检测ArrayDeque的 size和 empty

 public int size() {
        return (tail - head) & (elements.length - 1);
    }
    public boolean isEmpty() {
        return head == tail;
    } 

常规迭代器

public Iterator<E> iterator() {
        return new DeqIterator();
    }
private class DeqIterator implements Iterator<E> {
     
        private int cursor = head;

        private int fence = tail;

        private int lastRet = -1;

        public boolean hasNext() {
            return cursor != fence;
        }

        public E next() {
            if (cursor == fence)
                throw new NoSuchElementException();
            @SuppressWarnings("unchecked")
            E result = (E) elements[cursor];
            // This check doesn't catch all possible comodifications,
            // but does catch the ones that corrupt traversal
            if (tail != fence || result == null)
                throw new ConcurrentModificationException();
            lastRet = cursor;
            cursor = (cursor + 1) & (elements.length - 1);
            return result;
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            if (delete(lastRet)) { // if left-shifted, undo increment in next()
                cursor = (cursor - 1) & (elements.length - 1);
                fence = tail;
            }
            lastRet = -1;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            Object[] a = elements;
            int m = a.length - 1, f = fence, i = cursor;
            cursor = f;
            while (i != f) {
                @SuppressWarnings("unchecked") E e = (E)a[i];
                i = (i + 1) & m;
                if (e == null)
                    throw new ConcurrentModificationException();
                action.accept(e);
            }
        }
    }

降序迭代器,起始游标在尾节点,next方法是在数组前一位进行移动

public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }
private class DescendingIterator implements Iterator<E> {
        // 起始的游标为 尾节点
        private int cursor = tail;
        private int fence = head;
        private int lastRet = -1;

        public boolean hasNext() {
            return cursor != fence;
        }
        // next 是将游标在数组的位置向前移动一位
        public E next() {
            if (cursor == fence)
                throw new NoSuchElementException();
            cursor = (cursor - 1) & (elements.length - 1);
            @SuppressWarnings("unchecked")
            E result = (E) elements[cursor];
            if (head != fence || result == null)
                throw new ConcurrentModificationException();
            lastRet = cursor;
            return result;
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            if (!delete(lastRet)) {
                cursor = (cursor + 1) & (elements.length - 1);
                fence = head;
            }
            lastRet = -1;
        }
    }

 

看这个ArrayDeque的源码

有趣的地方是 可以直接使用栈、队列的方法名当成 栈、队列用,

还有一个降序迭代器descendingIterator反向遍历更方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值