1 类继承关系
默认的优先级队列,实现了netty中定义的优先级队列接口:PriorityQueue。
2 代码详情
DefaultPriorityQueue
类签名
public final class DefaultPriorityQueue extends AbstractQueue
implements PriorityQueue<T>
继承了jdk的AbstractQueue
实现了netty定义的优先级队列接口PriorityQueue
优先级队列中放的元素的类型需要是PriorityQueueNode
字段
比较器comparator
- private final Comparator comparator;
队列数组queue
-
private T[] queue;
队列元素个数size
-
private int size;
公有方法
public boolean contains(Object o)
- 判断是不是PriorityQueueNode的实例,不是的话return false
- 调用PriorityQueueNode的 int priorityQueueIndex(DefaultPriorityQueue<?> queue);方法获取这个node在这个队列中的位置i,然后直接比较o.equals(queue[i])
public boolean containsTyped(T node)
- 逻辑和上面一样,只是说这里有泛型限定了入参的类型,所以不需要在做实例的类型判断
public void clear()
- 遍历所有this.queue将数组所有的位置都赋值为null,this..size=0,并且将PriorityQueueNode中记录的它在数组中的位置赋值为-1,通过调用 void priorityQueueIndex(DefaultPriorityQueue<?> queue, int i);
public void clearIgnoringIndexes()
- 实现的是接口PriorityQueue中的方法
- 这样的意思是说,this.queue中的数组中的内容都没有变化
public boolean offer(T e)
- 1 调用e的 int priorityQueueIndex(DefaultPriorityQueue<?> queue);获取它在这个优先级队列中的位置,如果它的位置不等于-1,那么说明它已经在队列中了,那么这个时候则抛出异常
- 2 如果队列的大小已经达到数组的大小了,则进行扩容,通过Arrays.copyof方法,这里采用的策略是小的时候增大一倍,如果大的时候则增大50%
- 3 使得++size
- 4 将e插入这个优先级队列,实际是一个最小堆,采用的算法是从下晚上推,假设现在的e是要插入的位置是最后一个位置,然后和它的父节点比较如果父节点比它大,那么则和它的父节点交换位置,然后继续往上推,直到它的父节点比它小,然后调用让节点去记录它在数组中的位置
public T poll()
- 如果size=0, 则return null
- 将第一个元素,即最小的那个元素设置的在数组中的位置赋值为-1
- --size
- 同时将原先最后一个元素所处的最后一个赋值为null
- 如果size > 0,则往下推,所用的算法为,把原来的最后一个元素放到数组的第一个位置,然后往下推,如果它的两个子节点没有都比自己大,则将两个子节点中较小的那个和自己交换位置,然后继续往下推,直到两个子节点的大小都比自己大
public T peek()
- 直接返回数组的第一个元素就可以
- return (size == 0) ? null : queue[0];
public boolean removeTyped(T node)
- 1 拿到这个节点在数组中的位置
- 2 检验当前这个位置的节点和这个节点是否相等,不等待则return false
- 3 否则将这个节点在这个数组中的位置设置为-1:node.priorityQueueIndex(this, INDEX_NOT_IN_QUEUE);
- 4 --size
- 5 如果这个要删除的节点,刚好位于数组的最后一个位置,则直接将最后一个位置赋值为null
- 6 将数组中的最后一个位置的元素放到当前被删除的这个位置,然后将最后一个位置赋值为null,之后判断如果比原来大,则往下推,比原来小,则往上推
public boolean remove(Object o)
- 调用上面的public boolean removeTyped(T node)
public void priorityChanged(T node)
- 语义:这个node的优先级已经改变,那么需要调整这个最小堆中元素的顺序
- 1 判断是否这个队列中的节点,如果不是则直接return
- 2 如果这个节点在堆的顶端,则从堆顶往下推
- 3 否则需要判断下是需要往下推还是往上推:如果比它的父节点小了,则证明它比原值小了,于是就要往上推,否则就要往下推