在Java中,PriorityQueue
是一个基于优先级的无界队列,它实现了 Queue
接口。PriorityQueue
按照元素的自然顺序或者构造时提供的 Comparator
来对元素进行排序。元素按照优先级顺序被访问,优先级最高的元素最先被移除。
特性
- 优先级顺序:元素根据其自然顺序或者构造时提供的
Comparator
进行排序。 - 无界:
PriorityQueue
是无界的,但要注意内存限制。 - 线程不安全:
PriorityQueue
本身不是线程安全的。如果需要线程安全的优先级队列,可以使用PriorityBlockingQueue
。
方法
add(E e)
:将元素添加到队列中。offer(E e)
:将元素添加到队列中,如果成功返回true
,否则返回false
。peek()
:返回但不移除队列头部的元素,如果队列为空返回null
。poll()
:返回并移除队列头部的元素,如果队列为空返回null
。remove()
:返回并移除队列头部的元素,如果队列为空抛出NoSuchElementException
。
代码实现
在Java中,PriorityQueue
是一个基于优先级堆的数据结构,实现了 Queue
接口。它确保队列元素根据其自然顺序或者通过构造时提供的 Comparator
进行排序。
1. 默认的自然排序(升序)
默认情况下,PriorityQueue
使用元素的自然顺序,即元素的 Comparable
实现。如果没有提供 Comparator
,并且元素没有实现 Comparable
接口,将会抛出 ClassCastException
。
代码示例
import java.util.PriorityQueue;
public class NaturalOrderExample {
public static void main(String[] args) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 添加元素
pq.add(5);
pq.add(1);
pq.add(3);
// 移除并返回队列头部的元素
while (!pq.isEmpty()) {
System.out.println(pq.poll()); // 输出 1, 3, 5
}
}
}
2. 自然排序——实现Comparable接口
如果元素类实现了 Comparable
接口并重写了 compareTo
方法,那么 PriorityQueue
将使用这个实现来排序元素。
代码示例
import java.util.PriorityQueue;
class Student implements Comparable<Student> {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
// 首先比较成绩
int scoreCompare = Integer.compare(this.score, other.score);
if (scoreCompare != 0) {
// 如果成绩不同,直接返回成绩的比较结果
return scoreCompare;
} else {
// 如果成绩相同,再比较名字
return this.name.compareTo(other.name);
}
}
@Override
public String toString() {
return name + ": " + score;
}
}
public class ComparableExample {
public static void main(String[] args) {
PriorityQueue<Student> pq = new PriorityQueue<>();
// 添加学生
pq.add(new Student("Alice", 88));
pq.add(new Student("Bob", 95));
pq.add(new Student("Charlie", 90));
// 移除并返回队列头部的元素
while (!pq.isEmpty()) {
System.out.println(pq.poll()); // 输出 Alice: 88, Charlie: 90, Bob: 95
}
}
}
3. 定制排序——实现Comparator接口
通过构造函数传递一个 Comparator
实例来定义排序规则。这种方式提供了更大的灵活性,因为排序逻辑可以独立于元素类。
代码示例
import java.util.Comparator;
import java.util.PriorityQueue;
class Student {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return name + ": " + score;
}
}
public class ComparatorExample {
public static void main(String[] args) {
Comparator<Student> comparator = new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.score, s2.score); // 降序排序
}
};
PriorityQueue<Student> pq = new PriorityQueue<>(comparator);
// 添加学生
pq.add(new Student("Alice", 88));
pq.add(new Student("Bob", 95));
pq.add(new Student("Charlie", 90));
// 移除并返回队列头部的元素
while (!pq.isEmpty()) {
System.out.println(pq.poll()); // 输出 Bob: 95, Charlie: 90, Alice: 88
}
}
}
总结
- 默认的自然排序:使用元素的自然顺序,适用于基本数据类型和实现了
Comparable
接口的类。 - 自然排序——实现Comparable接口:元素类实现了
Comparable
接口,可以控制排序规则。 - 定制排序——实现Comparator接口:通过构造函数传递
Comparator
实例,提供了排序逻辑的灵活性。
这三种方法各有优势,选择哪一种取决于具体的应用场景和需求。
这些示例展示了如何使用 PriorityQueue
来根据元素的自然顺序或者自定义 Comparator
来管理元素的优先级。可以根据具体需求来选择合适的排序方式。