理解Java队列接口Queue的设计

Queue接口不属于Java并发包下面的类,它是java.util下面的一个接口,虽然这个接口跟并发没有直接关系,但是它抽象和定义了在Java里面队列的通用方法,最重要的是这个类也是Java并发大神Doug Lea设计的,所以学习和了解这个接口是非常有必要的。

Queue队列接口在实现上又继承了Collection接口,而Collection接口又继承了 Iterable接口,所以继承了这两个接口的定义的方法功能,另外Queue接口拥有的直接子类如下:

AbstractQueue
ArrayBlockingQueue
ArrayDeque
ConcurrentLinkedDeque
ConcurrentLinkedQueue
DelayQueue
LinkedBlockingDeque
LinkedBlockingQueue
LinkedList
LinkedTransferQueue
PriorityBlockingQueue
PriorityQueue
SynchronousQueue

但在这里我们重点关注其本身的定义的方法,其本身共定义了6个方法如下:

boolean add(E e) 
boolean offer(E e)
E remove()
E poll()
E element()
E peek()

Queue接口除了具有Collection接口基本的操作能力之外还提供了额外的插入,提取,检查操作,这些操作又分两种形式,第一种如果方法调用失败就会抛出异常,第二种方法调用失败不会抛出异常而会返回一个指定的值,通常是null或者false。第二种的插入设计操作通常是给有界限队列实现的,因为在大多数实现中插入操作不能失败。

我们通过一个表来总结下上面的几个方法:

操作

失败抛出异常

失败返回指定的值

插入

add(e)

offer(e)

移除

remove()

poll()

检查

element()

peek()

在Java的Queue队列接口实现里面,并不是所有的实现都符合队列FIFO先进先出的定义,在其子类实现中PriorityQueue这个优先级队列,就不是按照先进先出设计的,这个类是根据提供的比较器通过对优先级的排序来决定出队的顺序或者根据自然序比较。

此外还有一种LIFO后进先出的队列(或者叫栈),不管使用哪种排序规则,调用remove或者poll方法移除的都是队列头部的元素,在FIFO先进先出队列下,所有新增的节点都会被插入到队列的尾部,其他类型的队列使用不同的处理规则,每个队列的子类实现队列接口时必须指定排序的规则。

offer方法在插入数据失败的时候会返回false,这与Collection.add方法是不一样的,如果add方法添加失败则会抛出对应的异常,offer方法设计的目的是认为当插入失败的时候可以看成这是正常的情况,这就是说允许插入失败,而不抛出异常仅仅返回指定的false,一般用于固定大小(有边界)的队列。

remove和poll方法用来移除和返回队列的头节点,这个移除操作依赖队列的实现类是如何定义其排序规则的,这个在上面提过。这两个方法的不同之处在于当队列是空的时候,remove方法会抛出异常,而poll方法会返回一个null值。

此外element和peek方法会返回队列的头部的节点,但不会移除,可以理解仅仅是偷看一下。

队列接口中没有定义阻塞队列的方法,因为阻塞方法通常是用在并发编程中,这些方法在调用时会如果队列满了或者空了会进入阻塞状态,有关阻塞的队列定义在Queue接口的子类BlockingQueue接口中,这个接口继承了Queue接口。

最后,关于Queue队列的设计,还有两个注意点:

(1)队列的实现通常不允许插入null值,尽管一些队列实现了,如LinkedList就没有禁止,即使LinkedList可以插入null值,但我们在实际使用的时候也不应该向队列插入null值,因为null值通常用于poll方法表示当前队列没有元素了,但如果允许插入null值,这个方法就有歧义,所以我们在使用时候应该避免在队列中插入null值。

(2)队列的实现通常不需要重写该类的equasl和hashCode方法,代替使用Object类默认的定义,因为在队列里面一样的元素可能拥有不同的排序属性。

本文主要主要介绍了Java里面队列的基类接口Queue的设计和相关功能及注意事项,了解了基类接口的相关定义和功能,我们再去学习其下面的各种子类就会比较容易,Queue接口虽然名为队列,但其实这是广泛的定义,队列的底层算法主要是通过链表这种数据结构实现的,虽然也有通过数组的实现的,这也说明了数据结构与算法的重要性,不熟悉的同学,可以先了解一下它们的原理和优缺点。

原文发布于微信公众号 - 我是攻城师(woshigcs)

原文发表时间:2018-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我的技术专栏

Java锁机制(一)synchronized

18840
来自专栏Python小屋

Python中的队列结构及其用法

Python标准库queue提供了LILO队列类Queue、LIFO队列类LifoQueue、优先级队列类PriorityQueue,标准库collection...

44250
来自专栏xiaoxi666的专栏

你写的字符(串)忽略大小写比较函数真的严谨吗?

有时我们比较两个字符串时不考虑它们是大写还是小写;举个例子,在这种情况下我们认为“BanAna”和“baNaNA”是等价的。

9630
来自专栏编程

Python读书笔记5

上期分享了Python相关的字符串应用,重点分享了转义字符。今天和大家分享和字符串相关的函数和应用。 一、字符串的合并! Python用“+”号可以连接两个文本...

22670
来自专栏闪电gogogo的专栏

Python——正则表达式

此篇文章结合小甲鱼的笔记和视频整理。 1 编译 Python 通过 re 模块为正则表达式引擎提供一个接口,同时允许你将正则表达式编译成模式对象,并用它们来进行...

295100
来自专栏Golang语言社区

转--Golang语言语法汇总

最近看了看GoLang,把Go语言的语法总结了一下,做个快速参考 数据类型 ---- var varName type,var var1,var2… type,...

364160
来自专栏Golang语言社区

Go语言语法汇总

最近看了看GoLang,把Go语言的语法总结了一下,做个快速参考 数据类型 ---- var varName type,var var1,var2… type,...

354130
来自专栏Golang语言社区

Go语言语法汇总

最近看了看GoLang,把Go语言的语法总结了一下,做个快速参考 数据类型 ---- var varName type,var var1,var2… type,...

44480
来自专栏吴伟祥

logback高级特性使用 原

logback支持类似于占位符的变量替换功能,即如果输出的msg里面带有{}符号且括号中间不带其他字符,那么logback在构造LoggingEvent的时候,...

7520
来自专栏Janti

干货——详解Java中的关键字

在平时编码中,我们可能只注意了这些static,final,volatile等关键字的使用,忽略了他们的细节,更深层次的意义。

11930

扫码关注云+社区

领取腾讯云代金券