PriorityQueue 是 Java 中的一个类,它实现了一个基于优先级的队列,允许元素按照指定的优先级进行处理。常见的应用场景包括任务调度、图的最短路径算法、合并有序数据等。以下是关于 PriorityQueue 一些常见的知识点:

1. 基本特性

  • PriorityQueue 是一个无界的队列,默认情况下,它是按照自然顺序(Comparable 接口)进行排序的。如果元素是自定义对象,可以通过提供一个 Comparator 来定义排序规则。
  • 它实现了 Queue 接口,因此支持常见的队列操作,例如 add()poll()peek() 等。
  • 元素是根据优先级顺序出队的,而不是入队的顺序。

2. 构造方法

PriorityQueue 提供了多个构造函数,常见的有:

  • 默认构造方法:根据元素的自然顺序进行排序。
     
    PriorityQueue<Integer> pq = new PriorityQueue<>();
  • 自定义排序规则:通过 Comparator 提供自定义排序顺序。
     
    PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
  • 初始容量和比较器:指定初始容量和排序规则。
     
    PriorityQueue<Integer> pq = new PriorityQueue<>(50, Comparator.naturalOrder());

3. 基本操作

  • add(E e):向队列添加元素。如果元素成功添加,返回 true,如果队列已满,则抛出异常。
  • offer(E e):向队列添加元素。如果元素添加成功,返回 true,否则返回 false(适用于有界队列的情况)。
  • poll():移除并返回队头元素,返回 null 如果队列为空。
  • peek():返回队头元素,但不移除它,返回 null 如果队列为空。
  • size():返回队列中元素的个数。
  • isEmpty():检查队列是否为空。

4. 排序

  • 初始容量和比较器:指定初始容量和排序规则。
    PriorityQueue<Integer> pq = new PriorityQueue<>(50, Comparator.naturalOrder());
  • 默认情况下,PriorityQueue 使用元素的自然顺序进行排序(即元素必须实现 Comparable 接口)。例如,对于 Integer 类型,队列会按升序排列。
  • PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
  • 🤣如果要按照自定义规则排序,可以传入一个 Comparator,例如:
     
  • PriorityQueue<long[]> queue = new PriorityQueue<>(((o1, o2) -> {
        if (o1[0] == o2[0]) return Long.compare(o1[1], o2[1]);
        else return Long.compare(o1[0], o2[0]);
    }));
  • 这里创建了一个优先队列,用来存储每个数组元素及其对应的索引。队列中的每个元素是一个 long[] 数组,其中 o1[0]o2[0] 是数组中的值,o1[1]o2[1] 是对应的索引。

    排序规则是:首先按照数组元素的值进行升序排序,如果值相等,则按照索引升序排序。

5. 访问队头元素

  • PriorityQueue 始终保证队头是优先级最高的元素(即最小的元素,或者最大,取决于比较器)。
  • 如果使用默认的比较器,队头元素是最小的。
     
    PriorityQueue<Integer> pq = new PriorityQueue<>();
    pq.add(3);
    pq.add(1);
    pq.add(2);
    System.out.println(pq.peek());  // 输出 1,因为 1 是最小的元素

6. 效率

  • 插入操作(add())和删除操作(poll())的时间复杂度为 O(log n),其中 n 是队列中元素的数量。
  • 获取队头元素(peek())的时间复杂度是 O(1)

7. 应用场景

  • 任务调度:可以用来按优先级调度任务,最小堆或最大堆可以表示任务的优先级。
  • 合并有序数据:例如合并多个有序文件时,可以使用 PriorityQueue 来动态获取当前最小的元素。
  • 图算法:例如 Dijkstra 最短路径算法中使用优先队列来获取当前最短路径的节点。

8. 最大堆与最小堆

  • 默认情况下,PriorityQueue 是最小堆,即优先级最高的元素在队头(值最小的元素在队头)。
  • 如果需要最大堆(即优先级最高的元素是值最大的),可以提供一个反向的比较器(Comparator.reverseOrder()):
     
    PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());

9. 线程安全

PriorityQueue 不是线程安全的。如果需要在多线程环境中使用,可以通过 Collections.synchronizedQueue 或使用 ConcurrentLinkedQueue 来保证线程安全,或者使用 PriorityBlockingQueue 来实现线程安全的优先级队列。

10. 队列的清空

  • clear():清空队列中的所有元素。
     
    pq.clear();
posted on 2025-05-31 15:21  fafrkvit  阅读(54)  评论(1)    收藏  举报