DefaultPriorityQueue

182 阅读3分钟

1 类继承关系

image.png 默认的优先级队列,实现了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 否则需要判断下是需要往下推还是往上推:如果比它的父节点小了,则证明它比原值小了,于是就要往上推,否则就要往下推