Queue the difference with Deque

Foreword

In the study of a collection of java source code, I found a rarely used but very interesting point: Queue and Deque, usually in writing leetcode often use LinkedList upward transition Deque as a stack or queue to use, but never knew Queue role so it is a good direct official documents.

text

concept


Seen from the figure, Queue and are inherited in Deque Collection, Deque is Queue subinterface.
Look at the official interpretation of the document below.

A linear collection that supports element insertion and removal at both ends. The name deque is short for "double ended queue" and is usually pronounced "deck". Most Deque implementations place no fixed limits on the number of elements they may contain, but this interface supports capacity-restricted deques as well as those with no fixed size limit.

A collection designed for holding elements prior to processing. Besides basic Collection operations, queues provide additional insertion, extraction, and inspection operations. Each of these methods exists in two forms: one throws an exception if the operation fails, the other returns a special value (either null or false, depending on the operation). The latter form of the insert operation is designed specifically for use with capacity-restricted Queue implementations; in most implementations, insert operations cannot fail.

From the explanation Deque, we can know: Deque is a double ended queue, which I understand double-side end of the queue, deque, you can insert or remove elements from end to end. The interpretation of the Queue, Queue is a simple FIFO queue.
Therefore, conceptually, Queue FIFO is single-ended queue, Deque is deque.
In use on, what is the difference?

use

From the graph we can see that, Queue has a direct subclass PriorityQueue, and directly Deque has two sub-categories: LinkedList and ArrayDeque.

  • PriorityQueue

I think the focus on the delineation of two words: no boundaries, priority heap. Then look at the source


In the first picture of the source, the apparent underlying data structure is an array PriorityQueue without borders describe, then pointed out that own PriorityQueue expansion mechanism, see grow specific method of PriorityQueue.
In the second third pictures, you can see when the element is inserted compareTo need to go through the process, then the most commonly used is that some extremes range of output, similar to the use of heap sort.

The following shows what positive and negative sequence output using three elements

private static void negativePrint(int[] nums) {
        PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        for(int temp:nums){
            queue.add(temp);
        }
        System.out.println();
        System.out.print("倒序输出:");
        for(int i=0;i<3;i++){
            System.out.print(queue.poll()+" ");
        }
    }

    private static void positivePrint(int[] nums){
        PriorityQueue<Integer> queue=new PriorityQueue<>();
        for(int temp:nums){
            queue.add(temp);
        }
        System.out.print("正序输出:");
        for(int i=0;i<3;i++){
            System.out.print(queue.poll()+" ");
        }
    }
正序输出:1 2 3 
倒序输出:9 8 8 

In some charts or enter the N-th maximum / small element would be more commonly used.

  • LinkedList and ArrayDeque

From the point of view official explanation, ArrayDeque is no initial capacity deque, LinkedList is a doubly linked list. And we can see, as the efficiency is higher than LinkedList ArrayDeque queue, while in the stack usage scenarios undoubtedly tail junction empty without judgment LinkedList more efficient.
The following shows ArrayDeque queue as well as the use LinkedList stack

private static void usingAsQueue() {
        Deque<Integer> queue=new ArrayDeque<>();
        System.out.println("队列为空:"+queue.isEmpty());   //判断队列是否为空
        queue.addLast(12);   //添加元素
        System.out.println("队列为空:"+queue.isEmpty());   //判断队列是否为空
        System.out.println(queue.peekFirst());   //获取队列首部元素
        System.out.println(queue.pollFirst());   //获取并移除栈顶元素
        System.out.println("队列为空:"+queue.isEmpty());   //判断队列是否为空
 }

private static void usingAsStack() {
        //作为栈使用
        Deque<Integer> stack=new LinkedList<>();
        System.out.println("栈为空:"+stack.isEmpty());   //判断栈是否为空
        stack.addFirst(12);
        System.out.println("栈为空:"+stack.isEmpty());   //判断栈是否为空
        System.out.println(stack.peekFirst());   //获取栈顶元素
        System.out.println(stack.pollFirst());   //获取并移除栈顶元素
        System.out.println("栈为空:"+stack.isEmpty());   //判断栈是否为空
        System.out.println("============================================");
    }

The stack is empty: true
stack is empty: false
12
12

The stack is empty: true

The queue is empty: true
queue is empty: to false
12 is
12 is
the queue is empty: true

hint

In Deque, the acquisition and removal methods are two elements, namely removeXxx and peekXxx.

When there is an element, the processing of both are the same. But when within Deque is empty, removeXxx directly thrown NoSuchElementException, and peekXxx will return null.

So in terms of the actual development or algorithm, it is recommended peekXxx method

其实ArrayDeque和LinkedList都可以作为栈以及队列使用,但是从执行效率来说,ArrayDeque作为队列以及LinkedList作为栈使用会是更好的选择。
另外,我在leetcode看到有人采用Vector下的Stack,这个同步加锁粒度过大(对象级),另外我觉得算法中没有线程同步的需要吧。

  • 小结

PriorityQueue可以作为堆使用,而且可以根据传入的Comparator实现大小的调整,会是一个很好的选择。
ArrayDeque通常作为栈或队列使用,但是栈的效率不如LinkedList高。
LinkedList通常作为栈或队列使用,但是队列的效率不如ArrayQueue高。

总结

在java中,Queue被定义成单端队列使用,Deque被定义成双端队列使用。
而由于双端队列的定义,Deque可以作为栈或者队列使用,而Queue只能作为队列或者依赖于子类的实现作为堆使用。

本文首发于cartoon的博客
转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/queue%E4%B8%8Edeque%E7%9A%84%E5%8C%BA%E5%88%AB/

Guess you like

Origin www.cnblogs.com/cartooon/p/11610655.html