JDK源码系列

JDK源码-Queue系列

2017-08-24  本文已影响68人  薛云龙

Queue

Deque

ArrayDeque

方法剖析

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];
    }

其中,最关键的地方是其中的位或运算.首先,那一大串的位或运算的目的是为了得到传入的numElements的下一个2的次方数.比如传入的10,则得到16;传入16,得到32.那么经过五次的位或运算和右移运算就能够得到2^k-1的数了.看下图:


最后,得到的数加1即可.这样运算的目的是为了提高效率,毕竟计算机对二进制数的处理是最快的.

head = (head - 1) & (elements.length - 1),这个与操作完美的解决了越界问题.
由于数组大小elements.length无论在初始化或者扩容时,都是的2的倍数,所以这里-1之后,剩下的所有位上都是1,与head-1与操作之后,正好达到了取模的操作.
即当head-1大于0,则(head - 1) & (elements.length - 1)等于head;当head-1 等于-1,(head - 1) & (elements.length - 1).元素此时放到数组的最后一个位置.

public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }

当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];
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = a;
        head = 0;
        tail = n;
    }
public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }
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;
    }
上一篇 下一篇

猜你喜欢

热点阅读