队列是一种特殊的线性表,遵循先入先出、后入后出的基本原则,
一般来说,它只允许在表的前端进行删除操作,而在表的后端进行插入操作,
但是java的某些队列运行在任何地方插入删除;比如我们常用的 LinkedList 集合,它实现了Queue 接口,因此,我们可以理解为 LinkedList 就是一个队列;
队列结构图
队列种类划分
队列的种类划分可以分为三种:
- 是否阻塞?
- 有界还是无界
- 单向链表还是双向链表
阻塞 / 非阻塞 :
阻塞队列
入列(添加元素):
入列时, 如果元素数量超过队列总数 , 会进行等待(阻塞) , 等队列的中的元素出列后,
元素数量未超过队列总数时,就会解除阻塞状态,进而可以继续入列;
出列(读取元素):
出列时,如果队列为空的情况下, 也会进行等待(阻塞) , 直到队列中入列了元素,即会接触阻塞状态
好处 :
可以防止队列
容器溢出
, 只要满了就会阻塞等待, 也就不存在溢出的情况
非阻塞队列
不管入列还是出列 , 都不会进行阻塞;
出列时 , 如果元素数量超出队列总数 , 则
会抛出异常
;出列时 , 如果队列为空,则取出空值;
总结:
-
只要是阻塞队列,都是
线程安全的
; -
一般情况下 , 非阻塞式队列使用的比较少 , 一般都是用阻塞式的队列比较多;
-
区分是否为阻塞队列的方法在于 看他是否有以下两个方法 :
-
出列阻塞方法: take( )
-
入列阻塞方法: put( )
有界/无界
有界
有界限,长度大小受限制
无界
- 无限大小 , 说是无限大小 , 其实是有限的 , 只不过超过界限时会进行扩容;
- 就像ArrayList一样在内部进行动态扩容
单向 / 双向链表
单向链表
每个元素中除了元素本身之外,还存储一个指针,这个指针指向下一个元素;
![单向链表](java队列.assets/单向链表-1657785970721.png)
双向链表
除了元素本身之外,还有两个指针,一个指针指向前一个元素的地址,另一个指针指向后一个元素的地址
![双向链表](java队列.assets/双向链表.jpg)
Queue(队列)接口方法:
队列提供了附加的
插入
、提取
和检查
操作。这些方法以两种形式存在:
- 一种在操作失败时抛出异常,
- 另一种返回特殊值(null或false,取决于操作)。在大多数实现中,插入操作不会失败。
增删查(抛异常)
方法名 | 作用 |
---|---|
boolean add(E e) | 在尾部增加一个元素,成功返回true 如果队列已满,则抛出一个IIIegaISlabEepeplian异常 |
E remove() | 移除并返回 队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常 |
E element() | 返回队列的头部信息,但不删除 如果队列为空,则抛出一个NoSuchElementException异常 |
增删查(返回特殊值)
这种插入操作形式是专门为使用容量受限的Queue实现而设计的;
方法名 | 作用 |
---|---|
boolean offer(E e) | 在尾部增加一个元素,成功返回true, 如果队列满了返回false 使用容量受限的队列时,这种方法通常更适合添加 |
E poll() | 检索并删除该队列的头部,如果该队列为空,则返回null。 |
E peek() | 检索但不删除该队列的头部,如果该队列为空,则返回null |
Deque(双端队列)接口方法
支持两端元素插入和移除的线性集合。 deque这个名字是“double ended queue(双端队列)”的缩写
这个接口定义了访问deque容器
两端元素
的方法。提供了插入、删除和检查元素的方法。
这些方法以两种形式存在:
- 一种在操作失败时
抛出异常
- 另一种
返回特殊值
(null或false,取决于操作)提供了对队列的头和尾操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXhThHBg-1668410534435)(java队列.assets/image-20220714174742689.png)]
增删查(抛异常)
First
Element (Head)
方法名 | 作用 |
---|---|
boolean addFirst(e) | 从头插入元素,如果没有空间,则抛出IllegalstateException异常 如果队列是有界的,最好使用offerFirst方法 |
E removeFirst() | 返回并删除头部第一个元素 , 如果没有 , 抛出异常 |
E getFirst() | 获取头部第一个元素 , 但是不删除 , 如果队列为空,抛出异常 |
Last
Element (Tail)
方法名 | 作用 |
---|---|
boolean addLast(e) | 从尾插入元素,如果没有空间,则抛出IllegalstateException异常 如果队列是有界的,最好使用offerLast方法 |
E removeLast() | 返回并删除尾部第一个元素 , 如果没有 , 抛出异常 |
E getLast() | 获取尾部第一个元素 , 但是不删除 , 如果队列为空,抛出异常 |
增删查(返回特殊值)
这种插入操作形式是专门为 使用容量受限的Deque实现而设计的;
First
Element (Head)
方法名 | 作用 |
---|---|
boolean offerFirst(e) | 从头插入一个元素 , 插入成功返回true , 插入失败返回 flase |
E pollFirst() | 返回并删除头部第一个元素 , 如果没有 , 返回null |
E peekFirst() | 获取头部第一个元素 , 但是不删除 , 如果没有 , 返回null |
Last
Element (Tail)
方法名 | 作用 |
---|---|
boolean offerLast(e) | 从尾插入一个元素 , 插入成功返回true , 插入失败返回false |
E pollLast() | 返回并删除尾部第一个元素 , 如果没有 , 返回null |
E peekLast() | 获取尾部第一个元素 , 但是不删除 , 如果没有 , 返回null |
总结:
Queue:
错误处理 | 抛出异常 | 返回特殊值 |
---|---|---|
入队列 | add(e) | offer(e) |
出队列 | remove( ) | poll( ) |
队首元素 | element( ) | peek( ) |
Deque:
头插入 | 头插入 | 尾插入 | 尾插入 | |
---|---|---|---|---|
抛出异常 | 返回特殊值 | 抛出异常 | 返回特殊值 | |
入队列 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
出队列 | removeFirst( ) | pollFirst( ) | removeLast( ) | pollLast( ) |
检索元素 | getFirst( ) | peekFirst( ) | getLast( ) | peekLast( ) |
双端队列(Deque):
LinkedList
ArrayDeque
ConcurrentlinkedDeque
阻塞队列:
DelayQueue 延迟队列
SynchronousQueue 同步队列
PriorityBlockingQueue 优先级队列
LinkedBlockingQueue 链表阻塞队列
ArrayBlockingQueue 数组阻塞队列
队列使用
双端队列
支持两端元素插入和移除的线性集合。 deque这个名字是“double ended queue(双端队列)”的缩写
LinkedList
双向链表 , 线程不安全 , 非阻塞 , 最多可以存入一个null
public static void main(String[] args) {
//创建双端队列
Deque<Integer> deque = new LinkedList<>();
dequeMethod(deque);
}
父类Queue的方法
//插入 deque.add(1); //在末尾插入一条数据,如果满了抛出异常 deque.offer(2); //在末尾插入一条数据 , 成功返回true , 失败返回false //查询 Integer element = deque.element(); //返回头部信息但不删除 , 如果队列为空,报错 Integer peek = deque.peek(); //返回头部信息但不删除 , 如果队列尾空,返回null //删除 Integer remove = deque.remove(); //返回并删除头部的数据 如果队列为空,报错 Integer poll = deque.poll(); //返回并删除 , 如果队列尾空 返回null
抛出异常的方法
//插入 deque.addFirst(1); //从头插入一个元素 , 如果没有空间 抛出异常 deque.addLast(2); //从尾插入一个元素 , 如果没有空间 抛出异常 //查询 Integer first = deque.getFirst(); //获取头部第一个元素 , 但是不删除 , 如果队列为空,抛出异常 Integer last = deque.getLast(); //获取尾部第一个元素 , 但是不删除 , 如果队列为空,抛出异常 //删除 Integer integer = deque.removeFirst(); //返回并删除头部第一个元素 , 如果没有 , 抛出异常 Integer integer1 = deque.removeLast(); //返回并删除尾部第一个元素 , 如果没有 , 抛出异常
返回特殊值的方法
//插入 deque.offerFirst(1); //从头插入一个元素 , 插入成功返回true , 插入失败返回 flase deque.offerLast(2); //从尾插入一个元素 , 插入成功返回true , 插入失败返回false //查询 Integer integer2 = deque.peekFirst(); //获取头部第一个元素 , 但是不删除 , 如果没有 , 返回null Integer integer3 = deque.peekLast(); //获取尾部第一个元素 , 但是不删除 , 如果没有 , 返回null //删除 Integer integer4 = deque.pollFirst