java中常用的几种队列介绍

一、前言

本文主要介绍下常见的几种实现队列的数据结构。首先我们看下百度百科中对队列的介绍:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。简单的来说,队列是一种固定了出入口(固定了入口和出口的位置)的容器,这种特性使得它具有先进先出的特点。下图是我个人通过阅读源码对几种接口和类作出的一个关系图。

 

二、常用的队列

1、Queue (接口)

队列(Queue)中主要有一下几种方法(包括自己的方法和继承父类Collection的方法):

(1) add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常;

(2) offer 添加一个元素并返回true 如果队列已满,则返回false;

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

(4) peek 返回队列头部的元素,如果队列为空,则返回null;

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

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

此处要着重注意add和offer的区别,peek和element的区别,以及poll和remove的区别;

2、Deque

Deque表示双向队列,指该队列两端的元素既能入队(offer)也能出队(poll),如果将Deque限制为只能从一端入队和出队,则可实现栈的数据结构。如果固定一端进另一端出的话,那么它就相当于一个普通的队列。Deque主要有如下的常用方法:

(1)addLast(E e):在队列尾部插入元素(失败抛异常)。
(2)offerLast(E e):在队列尾部插入元素(返回布尔值,成功返回true,失败返回false)。
(3)removeFirst():移除并返回头部元素,没有则抛异常。
(4)pollFirst():移除并返回头部元素,没有则返回null。
(5)getFirst():获取但不删除头部元素,若队列为空,则抛出NoSuchElementException异常。

(6)element():返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常;
(7)peekFirst():返回队列头部的元素,如果队列为空,则返回null;

当然Deque远远不止这些方法还有在尾部操作的一系列方法类似XXXLast()这样的,使用方法和头部的大致相同,这里就不一一介绍了。

3、AbstractQueue

这是个抽象类,继承自AbstractCollection,同时实现了Queue接口。在实际使用中并不是很多,这里列出是为了让大家了解下各个类接口之间的关系。主要有add(),remove(),clear(),element(),addAll()等方法,这里就不详细介绍了,有兴趣的同学可以自己去看下源码。

4、LinkedList

该类继承自抽象类AbstractSequentialList,实现了List,Deque,Cloneable(能克隆),Serializable(支持序列化)等接口。该类中也有很多的方法,但为了有针对性,本文主要介绍与队列有关的方法。该类中主要定义了三个变量:

(1)size:列表的长度

(2)first:指向列表第一个节点的指针。

(3)last:指向列表最后一个节点的指针。

该类主要有以下几种常用方法(与队列有关):

(1)get(int index):获取制定索引位置的元素;

(2)add(int index,E element):在指定索引位置插入指定元素;

(3)remove(int index):移除并返回指定索引位置的元素;

当然,其他队列常用的方法(Deque中的所有方法),它都有,由于使用差别不大,这里就不一一解释了。

5、ArrayDeque

ArrayDeque类继承于抽象类AbstractCollection,同时实现了Deque,Cloneable,Serializable等接口。该类主要有以下几个变量:

(1)elements:该变量为Object[]类型,用于存储元素的数组(可见ArrayDeque的底层是用数组实现的)。

(2)head:队列头部加入元素时加入位置的索引;

(3)tail:队列尾部加入元素时加入位置的索引;

(4)MIN_INITIAL_CAPACITY:数组的最小容量,jdk1.8中该值为8;(注:ArrayDeque中默认的初始容量为16,当容量不够用的时候会进行自动扩容,每次扩容为之前的2倍,如果不够的话会继续扩容,当然这些是在容量低于最大容量的前提下。)

相关的方法就不在介绍了,与Deque大同小异。主要在说下它与LinkedList的区别:

(1)底层实现方式不同:LinkedList是链表结构,ArrayDeque是数组结构

(2)对null值的处理,LinkedList允许插入null值,但ArrayDeque不允许会抛出NullPointerException异常;

(3)无法确定数据量时,LinkedList无影响,ArrayDeque扩容会影响性能。

6、PriorityQueue

PriorityQueue继承自AbstractQueue并实现了Serializable接口。是我们常说的优先队列,优先队列的作用是保证每次取出的元素都是队列中权重最小的。元素大小的判断可以通过元素本身的自然顺序来判断(comparator为null的情况),或者根据comparator中的逻辑来判断(comparator不为null)。该类主要有以下变量:

(1)queue:该变量为Object[]类型,用于存放PriorityQueue中的元素;

(2)size:int类型,表示当前队列中元素的数量

(3)comparator:Comparator<? super E> 类型,为比较器。为null表示自然排序。

(4)modCount:int类型,表示此优先队列修改结构的次数。

该类型中有关队列的方法此处也不在过多描述了,与Queue差不多。需要注意的是,该类在添加了元素或者删除了元素后,会通过comparator来自动排序。当comparator为null时通过siftUpComparable(添加)和siftDownComparable(删除)来维持有序,comparator不为null时,通过siftUpUsingComparator(添加)和siftDownUsingComparator(删除)来维持有序。这里就不在过多描述了,有兴趣的同学可以自己去看源码。该类中不允许放null值,其是通过完全二叉树结构的小顶堆来实现排序的。

三、总结

总的来说,在我们平时刷题使用中,实现队列比较常见的是这几种类型。一般使用较多的是LinkedList和ArrayDeque,当你需要一个有序的队列时,那么推荐使用priorityQueue。本文只是对这几种常见的队列作了一个简单的总结,由于能力有限,难免会有错误或遗漏之处,欢迎大家批评与指正。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值