Collection series Queue (eleven): ArrayDeque

We can see from the name, it is actually a two-way queue implementation, and the use of the underlying array implementation.

public class ArrayDeque<E> extends AbstractCollection<E>
                           implements Deque<E>, Cloneable, Serializable

As can be seen from the definition, which achieves Deque interface.

principle

To understand ArrayDeque principle, we will class member variables, constructors, two core methods introduced one by one.

Class member variables

// 数据数组
transient Object[] elements;
// 头结点
transient int head;
// 尾节点
transient int tail; 

From the class member variables we know, it does use the underlying storage array.

Construction method

ArrayDeque a total of three constructor:

public ArrayDeque() {
    elements = new Object[16];
} 

public ArrayDeque(int numElements) {
    allocateElements(numElements);
} 

public ArrayDeque(Collection<? extends E> c) {
    allocateElements(c.size());
    addAll(c);
}

It can be seen from the first constructor, which directly specifies the initial constructor ArrayDeque size is 16.

The core method

For two-way queue, its key approach is to: offer, poll, offerFirst, offerLast, pollFirst, pollLast. But in fact the content of these methods are similar, so we only offer and poll analysis method.

offer

public boolean offer(E e) {
    return offerLast(e);
}
    
public boolean offerLast(E e) {
    addLast(e);
    return true;
}
    
public void addLast(E e) {
    if (e == null)
        throw new NullPointerException();
    elements[tail] = e;
    // 当 tail 和 head 相遇时,表示队列已满,需要扩容
    if ( (tail = (tail + 1) & (elements.length - 1)) == head)
        doubleCapacity();
}

Here it is more difficult to understand where the judge:

if ( (tail = (tail + 1) & (elements.length - 1)) == head)
    doubleCapacity();

Because ArrayDeque initial capacity is 16, and each expansion is expanded to twice the original, so ArrayDeque capacity is always a power of two. Therefore, the above fact is determined when the queue is not full, adding the equivalent of an operation for the tail.

if ( (tail = (tail + 1)) == head)
    doubleCapacity();

Do so is an object of the operation when the tail reaches the end of the array can be automatically switched to 0. We can assume that this array size is 16, but this time a tail point 15, i.e. the end node. Then offer operation performed at this time, we calculated (tail + 1) & (elements.length - 1)will be as shown below:

10000   // tail + 1 = 15 + 1 = 16
01111   // element.length - 1 = 16 -1 =15
00000   // 结果为0

The calculated result is 0, that is to say the tail pointer to the 0 position.

poll

public E poll() {
    return 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 = h + 1
    // 当处于队列末尾时,会切到队列头
    head = (h + 1) & (elements.length - 1);
    return result;
}

poll method is similar to methods offer, in the final moment of the head node is also added with the same method.

to sum up

After reading achieve ArrayDeque class, we could not help but think of LinkedList realized, because they are both two-way queue, but a realization takes an array, a linked list implementation. So they do what similarities and differences?

By querying some of the information found, in fact, both of them in the function and efficiency is not much different. If you need to use two-way beep columns, ArrayDeque relative LinkedList to be better. Because direct use LinkedList respect ArrayDeque storage array, you need to use the LinkedList storage node. So LinkedList relative ArrayDeque need to consume more memory.

Differences array itself and in that the difference list query and modify, but for the queue, its operations are carried out at the head and tail. So the difference array and a linked list does not reflect any body in the queue. The review Published ArrayDeque and LinkedList, we will find ArrayDeque released in JDK 1.6, while LinkedList released in JDK 1.2. So from that point of view, we have reason to believe ArrayDeque actually optimized version of the LinkedList.

If you are interested LinkedList and ArrayDeque differences, I recommend reading the article: the Java: ArrayDeque vs. LinkedList

Guess you like

Origin www.cnblogs.com/chanshuyi/p/java_collection_11_array_deque.html