欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构:Queue

程序员文章站 2022-06-08 08:10:14
...

Queue列队

1、Queue是典型的先进先出容器,FIFO(first-in-first-out),通俗点说就,这个容器就像一个管道,从一端放入从另一端取出,放入的顺序和取出的顺序是相同的。下面是在百度上搜索的一张图,很形象:

数据结构:Queue

2、Queue是一个接口类,继承至Collection接口,与List、Set同属于Collection的子类Interface

数据结构:Queue

 

3、Queue除了继承了Collection的接口外,自身拥有以下个接口:

数据结构:Queue

add :往列队中添加一个元索,如果队列已满,则抛出一个IIIegaISlabEepeplian异常

element:返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常

offer:添加一个元素,成功返回true,如果队列已满,则返回false

peek:返回队列头部的元素,如果队列为空,则返回null

poll:移除并返回队列头部的元素,如果队列为空,则返回null

remove:移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常

3.1、个方法区别

offer & add区别
一些队列有大小限制,如果想在容量满了的队列中加入元素,会被拒绝。

offer()方法将一个元素插入队尾,成功返回true,失败返回false,一般在queue容量有限制并且满员的情况下会插入失败;

add()方法将一个元素插入队尾,queue容量如果满了,插入将会失败,失的时候会抛出异常;

peek & element区别
element() peek() 都是在不移除元素的情况下返回列队头部元素。

在队列为空的情况下 peek() 返回 null,而element() 将抛出NoSuchElementException异常

poll & remove区别
remove() poll() 方法都移除并返回队列头部元素(head)。

poll() 方法在集合为空的时候返回 null,remove() 则抛出NoSuchElementException异常

 

4、Queue的子类有4个

数据结构:Queue

 

5、AbstractQueue:

一个抽象类,对Queue中的接口做了基本的实现

public abstract class AbstractQueue<E>
    extends AbstractCollection<E>
    implements Queue<E> {

    /**
     * Constructor for use by subclasses.
     */
    protected AbstractQueue() {
    }

    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

    public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

    public E element() {
        E x = peek();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

    public void clear() {
        while (poll() != null)
            ;
    }

    public boolean addAll(Collection<? extends E> c) {
        if (c == null)
            throw new NullPointerException();
        if (c == this)
            throw new IllegalArgumentException();
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

}

AbstractQueue其拥有以下子类

数据结构:Queue

 

6、BlockingQueue

 接口,一个阻塞式的队列

1)检索元素时,如果队列为空,便阻塞等待,直到列队中有元素了再进行操作,

2)存储元素时,如果空间不够,阻塞等待直到有空间可以用

下面是该类各个接口的源码及解释

 

public interface BlockingQueue<E> extends Queue<E> {
    /**
     * 如果可以在不违反容量限制的情况下立即执行此操作,将指定的元素插入队列,成功时返回true,
     * 如果当前没有空间,则抛出异常IllegalStateException。使用有限容量队列时,
     * 通常最好使用offer
     */
    boolean add(E e);

    /**
     * 如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此队列,成功时返回true,
     * 如果当前没有可用空间,则返回false。使用容量限制队列时,
     * 此方法通常优于add,可能插入元素会失败,此时仅仅会抛出一个异常
     */
    boolean offer(E e);

    /**
     * 往列队中插入指定元素,如果列队空间不够则等待空间可用
     */
    void put(E e) throws InterruptedException;

    /**
     * 将指定的元素插入队列,如果空间不够,则等待指定的时间。
     * 
     */
    boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 检索并删除此队列的头部元素,如果没有可用元素,则阻塞等待,直到有元素可用。
     */
    E take() throws InterruptedException;

    /**
     * 检索并删除此队列的头部元素,如果没有可用元素,则阻塞等待指定时间,指定时间内还是没有元素可用,则结束。
     */
    E poll(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 返回理想情况下此队列可以添加的元素的数量(在没有内存或资源限制的情况下)接受没有阻塞,或 
     * Integer.MAX_VALUE},如果没有内在限制
     */
    int remainingCapacity();

    /**
     * 
     * 从此队列中删除指定元素的单个实例,如果该实例存在。更确切地说,如果此队列包含一个或多个此元素,会通过 
     * o.equals(e)来进行比较,删除首先满足条件的元素,并会返回true,
     */
    boolean remove(Object o);

    /**
     * 
     * 如果此队列包含指定的元素,则返回true,通过 o.equals(e)来进行比较
     * 
     */
    boolean contains(Object o);

    /**
     * 从队列中移除所有可用元素,并将它们添加到指定集合中。此操作可能比重复轮询此队列更高效。
     * 尝试向集合c添加元素时可能会失败,这将导致抛出关联的异常时元素丢失,元素既不在集合C中,也不在原列队集合中。
     * 将队列自身元素排到自身会抛出IllegalArgumentException
     * 此外,操作正在被修改的集合时,则此操作是不确定的
     */
    int drainTo(Collection<? super E> c);

    /**
     * 与上面的重载方法不同的是,增加了一个最大元素的限制
     */
    int drainTo(Collection<? super E> c, int maxElements);
}

 

7、Deque:

Deque是继承自Queue的一个Interface,deque 是双端队列,全名double-ended queue,是一种具有队列和栈的性质的数据结构。

双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行,也就是说,插入和删除操作只能在表的两端进行。双端列队看起来似乎比栈和队列更灵活,但实际在应用程序中远不及栈和队列有用。

7.1、Deque个方法的作用

void push(E) 向双端队列表示的栈中压入一个元素,失败时抛出异常IllegalStateException
void addFirst(E) 向双端队列头部插入一个指定元素,失败时抛出异常
void addLast(E) 向双端队列尾部插入一个元素,失败时抛出异常
boolean offerFirst(E) 向双端队列头部加入一个元素,失败时返回false
boolean offerLast(E) 向双端队列尾部加入一个元素,失败时返回false


E pop() 从双端队列表示的栈中弹出一个元素。换句话说,删除并返回此双端队列的第一个元素,队列为空时抛出异常
boolean removeFirstOccurrence(Object) 删除第一次出现的指定元素,不存在时返回false
boolean removeLastOccurrence(Object) 删除最后一次出现的指定元素,不存在时返回false
E removeFirst() 检索并移除队列头部元素,队列为空时抛出异常
E removeLast() 检索移除队列尾部元素,队列为空时抛出异常
E pollFirst() 检索移除队列头部元素,队列为空时返回null 
E pollLast() 检索移除队列尾部元素,队列为空时返回null 


E getFirst() 获取队列头部元素,队列为空时抛出异常
E getLast() 获取队列尾部元素,队列为空时抛出异常
E peekFirst() 获取队列头部元素,队列为空时返回null
E peekLast() 获取队列尾部元素,队列为空时返回null

 

迭代器
Iterator<E>    descendingIterator() 返回队列反向迭代器

下面实在网上搜的一幅图来表示deque,比我自己画的要好

数据结构:Queue

 

8、ConcurrentLinkedQueue

ConcurrentLinkedQueue是一个基于链接节点的*线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现
类结构图如下:

数据结构:Queue

 

ConcurrentLinkedQueue由head节点和tail节点组成,每个Node节点由节点元素(item)和指向下一个节点的引用(next)组成,节点与节点之间就是通过这个next关联起来,从而组成一张链表结构的队列。默认情况下head节点存储的元素为空,tair节点等于head节点

public ConcurrentLinkedQueue() {
    head = tail = newNode(null);
}

下面一片技术贴讲得很好:http://ifeve.com/concurrentlinkedqueue/

9、阻塞列队和非阻塞列队

 

阻塞队列(BlockingQueue)提供了可阻塞的put和take方法,它们与可定时的offer和poll是等价的。如果Queue已经满了,put方法会被阻塞直到有空间可用;如果Queue是空的,那么take方法会被阻塞,直到有元素可用。Queue的长度可以有限,也可以无限;无限的Queue永远不会充满,所以它的put方法永远不会阻塞。


阻塞队列(BlockingQueue)在队列容量达到上限,往列队里添加元素的操作会被阻塞;当队列为空,从队列中获取元素的操作将会被阻塞。试图往容量已满的阻塞队列中添加新元素的线程会被阻塞,直到有其他的线程使操作队列,让该队列有可用空间出现,即从该队列中移除元素一个、多个元素,或者清空队列。从空的阻塞队列中获取元素的线程将会被阻塞,直到有其他的线程往空的队列插入新的元素。

阻塞列队:

  1. ArrayBlockingQueue:基于数组的并发阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口
  2. SynchronousQueue :并发同步阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口
  3. DelayQueue:延期阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口
  4. LinkedBlockingQueue:基于链表的FIFO阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口
  5. LinkedBlockingDeque:基于链表的FIFO双端阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口
  6. PriorityBlockingQueue::带优先级的*阻塞队列,继承自AbstractQueue,实现了BlockingQueue接口

非阻塞列队:

  1. ConcurrentLinkedQueue:基于链表的并发队列,继承自AbstractQueue,实现了Queue接口
  2. PriorityQueue:带优先级的*队列,继承自AbstractQueue,实现了BlockingQueue接口
  3. ArrayDeque,:数组双端队列,继承自AbstractCollection,实现了Deque接口

 

相关标签: queue