您的位置:首页 > 产品设计 > UI/UE

Deque与LinkedBlockingDeque深入分析

2017-04-12 09:46 483 查看
Queue除了前面介绍的实现外,还有一种双向的Queue实现Deque。这种队列允许在队列头和尾部进行入队出队操作,因此在功能上比Queue显然要更复杂。下图描述的是Deque的完整体系图。需要说明的是LinkedList也已经加入了Deque的一部分(LinkedList是从jdk1.2 开始就存在数据结构)。

 



Deque在Queue的基础上增加了更多的操作方法。



从上图可以看到,Deque不仅具有FIFO的Queue实现,也有FILO的实现,也就是不仅可以实现队列,也可以实现一个堆栈。

同时在Deque的体系结构图中可以看到,实现一个Deque可以使用数组(ArrayDeque),同时也可以使用链表(LinkedList),还可以同实现一个支持阻塞的线程安全版本队列LinkedBlockingDeque。


1、ArrayDeque实现Deque

 



对于数组实现的Deque来说,数据结构上比较简单,只需要一个存储数据的数组以及头尾两个索引即可。由于数组是固定长度的,所以很容易就得到数组的头和尾,那么对于数组的操作只需要移动头和尾的索引即可。

特别说明的是ArrayDeque并不是一个固定大小的队列,每次队列满了以后就将队列容量扩大一倍(doubleCapacity()),因此加入一个元素总是能成功,而且也不会抛出一个异常。也就是说ArrayDeque是一个没有容量限制的队列。

同样继续性能的考虑,使用System.arraycopy复制一个数组比循环设置要高效得多。


1.1、ArrayDeque的源码解析

 

[java] view plaincopy

//数组双端队列ArrayDeque的源码解析  

public class ArrayDeque extends AbstractCollection implements Deque, Cloneable, Serializable{  

      

    private transient E[] elements;  

      

    private transient int head;  

      

    private transient int tail;  

      

    private static final int MIN_INITIAL_CAPACITY = 8;  

    // ******  Array allocation and resizing utilities ******  

      

    private void allocateElements(int numElements) {  

        int initialCapacity = MIN_INITIAL_CAPACITY;  

        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 = (E[]) 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 = (E[])a;  

        head = 0;  

        tail = n;  

    }  

      

    private  T[] copyElements(T[] a) {  

        if (head < tail) {  

            System.arraycopy(elements, head, a, 0, size());  

        } else if (head > tail) {  

            int headPortionLen = elements.length - head;  

            System.arraycopy(elements, head, a, 0, headPortionLen);  

            System.arraycopy(elements, 0, a, headPortionLen, tail);  

        }  

        return a;  

    }  

      

    public ArrayDeque() {  

        elements = (E[]) new Object[16];  

    }  

      

    public ArrayDeque(int numElements) {  

        allocateElements(numElements);  

    }  

      

    public ArrayDeque(Collection
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: