PriorityQueue 一個基於優先級的無界優先級隊列。內部使用 Object 數組實現,默認大小是 11。
PriorityQueue 通過二叉小頂堆實現,具體說是通過完全二叉樹(complete binary tree)實現的小頂堆(任意一個非葉子節點的權值,都不大於其左右子節點的權值)
優先級隊列的元素按照其自然順序(從小到大)進行排序,或者根據構造隊列時提供的 Comparator 進行排序,具體取決於所使用的構造方法。
PriorityQueue 隊列不允許放入 null,也不允許插入不可比較的對象(沒有實現 Comparable 接口的對象)。
其實可以插入一個沒有實現 Comparable 接口的對象,此時再進行插入就會出現:java.lang.ClassCastException: demos.other.MyNode cannot be cast to java.lang.Comparable
。
PriorityQueue 隊頭指排序規則最小的那個元素。如果多個元素都是最小值則隨機選一個(待驗證)。
部分源碼如下:
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable {
private static final long serialVersionUID = -7720805057305804111L;
private static final int DEFAULT_INITIAL_CAPACITY = 11;
transient Object[] queue;
// The number of elements in the priority queue.
private int size = 0;
// The comparator, or null if priority queue uses elements' natural ordering.
private final Comparator<? super E> comparator;
transient int modCount = 0;
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}
public PriorityQueue(int initialCapacity,Comparator<? super E> comparator) {
// 實際上不需要至少有一個限制,但可以繼續保持1.5的兼容性
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
}
PriorityQueue 優先級規則可以根據具體需求而定製, 方式有 2 種:
- 添加元素自身實現 Comparable 接口,確保元素是可排序的對象。
- 添加元素沒有實現 Comparable 接口,可以在創建 PriorityQueue 隊列時直接指定比較器 Comparator。
構造隊列時提供的 Comparator 示例
import java.util.Comparator;
import java.util.PriorityQueue;
public class PriorityQueueDemo {
public static void main(String[] args) {
Comparator<MyNode> comparator = new Comparator<MyNode>() {
@Override
public int compare(MyNode o1, MyNode o2) {
return o1.x - o2.x;
}
};
PriorityQueue<MyNode> queue = new PriorityQueue<>(comparator);
queue.offer(new MyNode(4));
queue.offer(new MyNode(8));
queue.offer(new MyNode(1));
queue.offer(new MyNode(5));
queue.offer(new MyNode(7));
queue.offer(new MyNode(2));
while (queue.size() != 0) {
System.out.println(queue.poll());
}
}
}
class MyNode {
int x;
MyNode(int x) {
this.x = x;
}
@Override
public String toString() {
return "MyNode:" + x;
}
}
輸出:
MyNode:1
MyNode:2
MyNode:4
MyNode:5
MyNode:7
MyNode:8
可排序對象示例
import java.util.PriorityQueue;
public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue<MyComparableNode> queue = new PriorityQueue<>();
queue.offer(new MyComparableNode(4));
queue.offer(new MyComparableNode(8));
queue.offer(new MyComparableNode(1));
queue.offer(new MyComparableNode(5));
queue.offer(new MyComparableNode(7));
queue.offer(new MyComparableNode(2));
while (queue.size() != 0) {
System.out.println(queue.poll());
}
}
}
class MyComparableNode implements Comparable<MyComparableNode> {
int x;
MyComparableNode(int x) {
this.x = x;
}
@Override
public int compareTo(MyComparableNode o) {
return this.x - o.x;
}
@Override
public String toString() {
return "MyComparableNode:" + x;
}
}
輸出:
MyComparableNode:1
MyComparableNode:2
MyComparableNode:4
MyComparableNode:5
MyComparableNode:7
MyComparableNode:8