问:简单说说什么是 Queue 以及 PriorityQueue 与 LinkedList 的区别及特点?
答:首先 Queue 是一种模拟 FIFO 队列的数据结构,新元素插入(offer)到队列的尾部,访问元素(poll)返回队列头部,一般队列不允许随机访问队列中的元素。Queue 接口主要定义了如下几个方法:
//将指定元素加入队列尾部
void add (Object e );
// 获取队列头部元素,但是不删除该元素,如果队列为空抛出 NoSuchElementException 异常
Object element ();
// 将指定元素加入队列尾部(当使用有容量限制的队列时此方法比 add(Object e) 更好)
boolean offer (Object e );
// 获取队列头部元素,但是不删除该元素,如果队列为空返回 null
Object peek ();
// 获取队列头部元素并删除该元素,如果队列为空则返回 null
Object poll ();
// 获取队列头部元素并删除该元素,如果队列为空抛出 NoSuchElementException 异常
Object remove ();
LinkedList 是一个比较奇怪的类,其即实现了 List 接口又实现了 Deque 接口(Deque 是 Queue 的子接口),而 LinkedList 的实现是基于双向链表结构的,其容量没有限制,是非并发安全的队列,所以不仅可以当成列表使用,还可以当做双向队列使用,同时也可以当成栈使用(因为还实现了 pop 和 push 方法)。此外 LinkedList 的元素可以为 null 值。
PriorityQueue 是一个优先级列表队列,因为 PriorityQueue 保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的大小进行重新排序,所以当调用 peek 或者 pull 方法从队列头取元素时并不是取出最先进入队列的元素,而是取出队列中最小的元素(默认顺序),所以说 PriorityQueue 实质违反了 FIFO 队列的基本原则,从而成了优先级列表实现,同时 PriorityQueue 的实现是基于动态扩容数组的二叉树堆结构,其最大容量长度为 Int 大小,是非并发安全的队列。此外 PriorityQueue 的元素不可为 null 值。
问:PriorityQueue 是怎么确定哪一个元素的优先级最高的?
答:PriorityQueue 确定最高优先级元素使用的是堆数据结构,因为堆是一棵完全树,堆中某个节点的值总是不大于或不小于其父节点值的,常见的堆有二叉堆、斐波那契堆等,二叉堆是完全二叉树或者是近似完全二叉树的一种特殊堆,其分为最大堆和最小堆,最大堆中父结点值总是大于或等于任何一个子节点值,最小堆中父结点值总是小于或等于任何一个子节点值,由于二叉堆一直是自左向右自上向下一层层填充的,所以其可以用数组来表示而不是用链表,PriorityQueue 就是采用了基于动态数组的二叉堆来确定优先级。