数据结构:Queue

Queue列队

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

804515552.png-10.1kB

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

35e0cffeee1cc0489a45c50698f5484505d.jpg

 

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

6ced3275497110e21b29ba3a46b3ed5e588.jpg

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个

9e83d76d5540d62fc6b7f4a5ea10f904b7e.jpg

 

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其拥有以下子类

6859dd3691af1f96c5d71f266ba5ec452b8.jpg

 

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,比我自己画的要好

u=748234527,3999100646&fm=26&gp=0.jpg

 

8、ConcurrentLinkedQueue

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

aae6cec5899d2ba3dd0cc37fb4456877181.jpg

 

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接口

转载于:https://my.oschina.net/goboy/blog/1940660

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值