【Java集合框架库】PriorityQueue类

PriorityQueue类

PriorityQueue是一个基于优先级的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。该队列不允许使用 null 元素也不允许插入不可比较的对象(没有实现Comparable接口的对象)。

PriorityQueue 队列的队头元素指排序规则最小那个元素。如果多个元素都是最小值则随机选一个。

PriorityQueue 是一个无界队列,但是初始的容量(实际是一个Object[]),随着不断向优先级队列添加元素,其容量会自动扩容,无需指定容量增加策略的细节。

PriorityQueue的特点
PriorityQueue的继承结构

在这里插入图片描述

public class PriorityQueue<E> extends AbstractQueue<E>
    implements java.io.Serializable {
   
    ......
}
  • PriorityQueue继承于AbstractQueue类,说明它是一个基于优先级堆的极大优先级队列。此队列按照在构造时所指定的顺序对元素排序,既可以根据元素的自然顺序来指定排序,也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象。
  • PriorityQueue实现了Serializable接口,说明它支持序列化。public interface Serializable类通过实现 java.io.Serializable 接口以启用其序列化功能。
  • PriorityQueue内部实现了Iterator接口,说明它可以进行迭代器遍历。

但是需要注意的是,使用迭代器遍历,并不能保证其优先级顺序,原因是迭代器在进行遍历时采取的是层次遍历,一层一层进行遍历,并不能保证其左右孩子的准确性,如果需要按照优先级顺序进行遍历,则需要使用for循环遍历,通过poll()方法获取其队头元素。

PriorityQueue的特性
  • PriorityQueue类在Java1.5中引入并作为 Java Collections Framework 的一部分。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。
  • 优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。
  • 优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。
  • 优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。
  • PriorityQueue是非线程安全的,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于Java多线程环境。
PriorityQueue常用API
public boolean offer(E e); //将指定的元素插入此优先级队列。不能添加null元素。否则报出空指针异常。

public boolean add(E e); //将指定的元素插入此优先级队列。不能添加null元素。与offer()方法一致,实际上,该方法内部是调用offer()方法。

public boolean remove(Object o); //删除一个指定元素,如果元素不存在则返回false。

public E peek(); //取出队头元素但不删除,如果当前队头没有元素则返回null值。

public E element(); //取出队头元素但不删除,如果当前队头没有元素则抛出异常。

public E poll(); //取出队头元素并删除,如果当前队头没有元素则返回null值。
  • 常用方法实践:
import java.util.*;

public class PriorityQueueTest {
   
    public static void main(String[] args) {
   
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        //queue.offer(null); //offer方法不能添加null值
        //queue.element(); //获取队头获取,但不删除元素,若没有元素抛出异常
        //System.out.println(queue.peek()); //获取队头获取,若没有元素返回null值
        //queue.poll(); //获取队头元素并删除,若没有元素返回null值

        /**
         * 添加元素
         * 思考:
         *      (1)为什么没有指定优先级的比较原则,但是没有报错
         *      答:在Integer内部提供了大小比较方式
         *      (2)如何提供优先级队列的比较原则(与TreeMap中提供大小比较原则相同)
         *      答:相当于我们需要为优先级队列提供一个大小比较的原则,即向优先级队列提供比较器
         */
        queue.offer(1);
        queue.offer(999);
        queue.offer(33);
        queue.offer(17);

        /**
         * 迭代器方式遍历
         * 不会按优先级高低进行遍历,会按照底层数据结构的方式进行遍历,即按照最小根堆左右子树的方式遍历
         * 思考:为什么所有的元素在底层并没有按照优先级顺存储,他还能维护优先级顺序
         */
        Iterator<Integer> iterator = queue.iterator();
        while (iterator.hasNext()) {
   
            Integer next = iterator.next();
            System.out.println(next);
        }
    }
}
  • 执行结果:
1
17
33
999
PriorityQueue源码分析
1、成员变量
// 默认初始化大小
privatestaticfinalintDEFAULT_INITIAL_CAPACITY = 11;

// 用数组实现的二叉堆,下面的英文注释确认了我们前面的说法。
/**
 * Priority queue represented as a balanced binary heap: the two
 * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
 * priority queue is ordered by comparator, or by the elements'
 * natural ordering, if comparator is null: For each node n in the
 * heap and each descendant d of n, n <= d.  The element with the
 * lowest value is in queue[0], assuming the queue is nonempty.
 */
private transient Object[] queue ;

// 队列的元素数量
private int size = 0;

// 比较器
private final Comparator<? super E> comparator;

// 用于快速失败机制判断
private transient int modCount = 0;
2、构造方法
/**
 * 默认构造方法,使用默认的初始大小来构造一个优先队列,比较器comparator为空,这里要求入队的元素必须实现Comparator接口
 */
 public PriorityQueue() {
   
    this(DEFAULT_INITIAL_CAPACITY, null);
 }

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值