Queue接口
Queue
是 Java 集合框架中的一个接口,位于 java.util
包下,用来表示 单向队列数据结构。队列通常遵循 FIFO(First In First Out,先进先出)的原则,即最先插入的元素最先被移除。
特点
- FIFO 顺序:队列通常按照先进先出的顺序处理元素。
- 不允许插入
null
值:避免产生歧义
常见实现类
LinkedList
:实现了Queue
接口,适用于一般队列操作。PriorityQueue
:基于优先级的队列,元素按照优先级排序。ArrayDeque
:高效的双端队列实现,也可以用作普通队列。
常见方法
添加元素
boolean add(E e)
:将指定的元素插入队列。如果队列已满,会抛出IllegalStateException
异常。boolean offer(E e)
:将指定的元素插入队列。如果队列已满,返回false
。推荐使用此方法以避免异常。
移除元素
E remove()
:移除并返回队列头部的元素。如果队列为空,抛出NoSuchElementException
异常。E poll()
:移除并返回队列头部的元素。如果队列为空,返回null
获取队头元素
E element()
:返回队列头部的元素,但不移除。如果队列为空,抛出NoSuchElementException
异常。E peek()
:返回队列头部的元素,但不移除。如果队列为空,返回null
。boolean contains(Object o)
:检查队列中是否包含指定的元素。(继承自Collection
接口)
Deque接口
Deque
(双端队列)是 Java 集合框架中的一个接口,位于 java.util
包下。它扩展了 Queue
接口,允许在 队列的两端插入和移除元素,既支持 FIFO(先进先出),也支持 LIFO(后进先出) 操作。
特点
- 双端操作:支持从头部或尾部插入、删除、查看元素。
- 灵活性:可以用作 队列 或 栈。
- 不允许
null
元素:为了避免歧义,Deque
不允许存储null
。
常见实现类
ArrayDeque
:基于数组实现,性能高效。LinkedList
:基于链表实现,支持动态扩展。
常见方法
队列操作
添加元素
void addFirst(E e)
:将指定元素插入到双端队列的头部。如果操作失败,抛出异常。boolean offerFirst(E e)
:将指定元素插入到双端队列的头部。如果操作失败,返回false
void addLast(E e)
:将指定元素插入到双端队列的尾部。如果操作失败,抛出异常boolean offerLast(E e)
:将指定元素插入到双端队列的尾部。如果操作失败,返回false
删除元素
E removeFirst()
:移除并返回头部的元素。如果双端队列为空,抛出异常。E pollFirst()
:移除并返回头部的元素。如果双端队列为空,返回null
E removeLast()
:移除并返回尾部的元素。如果双端队列为空,抛出异常E pollLast()
:移除并返回尾部的元素。如果双端队列为空,返回null
获取元素
E getFirst()
:返回头部的元素,但不移除。如果双端队列为空,抛出异常。E peekFirst()
:返回头部的元素,但不移除。如果双端队列为空,返回null
E getLast()
:返回尾部的元素,但不移除。如果双端队列为空,抛出异常E peekLast()
:返回尾部的元素,但不移除。如果双端队列为空,返回null
栈操作
void push(E e)
:将元素压入到双端队列的头部,等价于入栈。E pop()
:移除并返回双端队列头部的元素,等价于出栈E peek()
:返回栈顶的元素
ArrayDeque类
特点
插入删除高效:
ArrayDeque
不需要维护节点指针,因此在时间和空间上更高效。- 插入和删除操作在队列的头部和尾部都具有 $O(1) $的性能(在动态扩容时性能可能下降)。
双端操作:
- 允许在 头部 和 尾部 插入、删除元素。
- 支持队列(FIFO)和栈(LIFO)操作。
动态扩容:
- 底层通过动态数组实现,当存储空间不足时,会自动扩容为原来的两倍。
不支持 null
元素:
- 为了避免混淆(例如,返回值为
null
时无法判断是队列为空还是插入了null
),ArrayDeque
不允许存储null
。
非线程安全:
ArrayDeque
没有内置的同步机制,若在多线程环境下使用,需要手动同步。
底层实现
ArrayDeque
底层通过数组实现,为了满足可以同时在数组两端插入或删除元素的需求,该数组还必须是循环的,即循环数组,也就是说数组的任何一点都可能被看作起点或者终点。
head
指向首端第一个有效元素,
tail
指向尾端第一个可以插入元素的空位
addFirst()
方法
addFirst(E e)
的作用是在Deque的首端插入元素,也就是在head
的前面插入元素,在空间足够且下标没有越界的情况下,只需要将 elements[--head] = e
即可。
|
|
addLast()
方法
addLast(E e)
的作用是在Deque的尾端插入元素,也就是在 tail
的位置插入元素,由于 tail
总是指向下一个可以插入的空位,因此只需要 elements[tail] = e
即可
|
|
pollFirst()
方法
pollFirst()
的作用是删除并返回队列首端元素,也即是head
位置处的元素。如果容器不空,只需要直接返回elements[head]
即可,当然还需要处理下标的问题。由于ArrayDeque
中不允许放入null
,当 elements[head] == null
时,意味着容器为空。
|
|
pollLast
方法
pollLast()
的作用是删除并返回队列尾端元素,也即是 tail
位置前面的那个元素
|
|
PriorityQueue类
PriorityQueue
是 Java 集合框架中的一个队列实现类,位于 java.util
包下,用于实现基于 优先级堆排序 的队列。它按照元素的自然顺序(Comparable
)或通过自定义比较器(Comparator
)定义的顺序对队列进行排序,每次从队列中获取或移除的都是 优先级最高的元素。
特点
- 底层实现:
PriorityQueue
底层基于 小顶堆 实现(默认为自然顺序),用一个动态调整大小的数组存储堆结构。
- 排序机制:
- 默认按照元素的自然顺序(对象需要实现
Comparable
接口)。 - 可以通过构造器传入自定义的
Comparator
定义排序规则。
- 默认按照元素的自然顺序(对象需要实现
- 非线程安全:
- 适用于单线程环境,多线程环境下需要使用外部同步机制或使用线程安全的队列(如
PriorityBlockingQueue
)。
- 适用于单线程环境,多线程环境下需要使用外部同步机制或使用线程安全的队列(如
- 允许
null
元素:- 不允许插入
null
元素。
- 不允许插入
- 元素的去重:
- 不提供去重功能,允许重复元素。
- 动态扩容:
- 底层数组的容量会根据需求动态调整。
堆
堆是一种完全二叉树,堆的特点是根节点的值最小(小顶堆)或最大(大顶堆),并且任意非根节点i的值都不大于(或不小于)其父节点的值。
在堆中,每个节点的下标和其在数组中的下标是一一对应的,假设节点下标为 i
,则其父节点下标为 (i-1)/2
,其左子节点下标为 2i+1
,其右子节点下标为 2i+2
。
小顶堆
|
|
大顶堆
|
|
示例
|
|