上一章写了一个基础优先级队列的实现,现在看下Doug Lea大神的源码.
PriorityQueue是一个无界队列,无界的实现采用数组扩张
/**
* Increases the capacity of the array.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
offer(add)加入数据
/**
* Inserts the specified element into this priority queue.
*
* @return {@code true} (as specified by {@link Queue#offer})
* @throws ClassCastException if the specified element cannot be
* compared with elements currently in this priority queue
* according to the priority queue's ordering
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
// 内容的长度
int i = size;
// 超过当前数据 扩展数组
if (i >= queue.length)
grow(i + 1);
// 加入到尾结点,开始上浮
siftUp(i, e);
size = i + 1;
return true;
}
PriorityQueue上浮逻辑
/**
* Inserts item x at position k, maintaining heap invariant by
* promoting x up the tree until it is greater than or equal to
* its parent, or is the root.
*
* To simplify and speed up coercions and comparisons, the
* Comparable and Comparator versions are separated into different
* methods that are otherwise identical. (Similarly for siftDown.)
*
* @param k the position to fill
* @param x the item to insert
*/
private void siftUp(int k, E x) {
if (comparator != null)
// 包含比较器的,开始上浮逻辑
siftUpUsingComparator(k, x, queue, comparator);
else
siftUpComparable(k, x, queue);
}
// 上浮逻辑
// k=>size的值(数组的最后一个数据)
// x=>插入的对象
// es=>整个二叉堆
// cmp=>比较器
private static <T> void siftUpUsingComparator(int k, T x, Object[] es, Comparator<? super T> cmp) {
while (k > 0) {
// 找到父节点,上浮一层的节点
int parent = (k - 1) >>> 1;
Object e = es[parent];
// 优先级不够 停止上浮
if (cmp.compare(x, (T) e) >= 0)
break;
es[k] = e;
// 从父节点开始继续上浮
k = parent;
}
es[k] = x;
}
拿出最优值,但不移除
public E peek() {
return (E) queue[0];
}
获取最优值,拿掉之后执行数深度重排
public E poll() {
// 二叉堆
final Object[] es;
// 头结点
final E result;
if ((result = (E) ((es = queue)[0])) != null) {
modCount++;
final int n;
// 移调后当前的size-1
final E x = (E) es[(n = --size)];
es[n] = null;
if (n > 0) {
final Comparator<? super E> cmp;
if ((cmp = comparator) == null)
siftDownComparable(0, x, es, n);
else
siftDownUsingComparator(0, x, es, n, cmp);
}
}
return result;
}
执行下沉
// k=>数头结点
// X=>替补上去的尾结点
// es=>二叉堆
// n=>拿掉头结点之后的size
// cmp=>比较器
private static <T> void siftDownUsingComparator(
int k, T x, Object[] es, int n, Comparator<? super T> cmp) {
// assert n > 0;
// 总层数
int half = n >>> 1;
while (k < half) {
// 子节点
int child = (k << 1) + 1;
// 子节点数据
Object c = es[child];
// 右子节点
int right = child + 1;
// 比较两个子节点中优先级高的
if (right < n && cmp.compare((T) c, (T) es[right]) > 0)
c = es[child = right];
// 优先级高的再和x进行比较
if (cmp.compare(x, (T) c) <= 0)
break;
// 交换
es[k] = c;
k = child;
}
es[k] = x;
}
- PriorityQueue 不是线程安全的
- 无界的代价是越界之后的数据复制
- 实用性和A说的一致,插入的值波动大,且无需排序.