先知道PriorityBlockingQueue 是利用數組存儲二叉堆實現。最小值(最優先)放在queue[0]位置。java
//刪除某個元素 public boolean remove(Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { int i = indexOf(o);//先找到元素的位置,見下面函數源碼 if (i == -1) return false; removeAt(i);//根據元素位置刪除數據,見下面函數源碼 return true; } finally { lock.unlock(); } } //獲取某個元素數組的下標 private int indexOf(Object o) { if (o != null) { Object[] array = queue; int n = size; for (int i = 0; i < n; i++) if (o.equals(array[i])) return i; } return -1; } //根據下標去刪除數據 private void removeAt(int i) { Object[] array = queue; int n = size - 1; if (n == i) // removed last element array[i] = null; else { E moved = (E) array[n];//保存最後一個元素 array[n] = null;//最後一個元素賦值null Comparator<? super E> cmp = comparator; if (cmp == null) siftDownComparable(i, moved, array, n);//以自實現Comparable接口對象爲例(實際上是把最後一個元素放到被刪除元素的位置,讓後經過,不斷降級的算法,再構造合法的堆結構),見下面函數源碼 else siftDownUsingComparator(i, moved, array, n, cmp); if (array[i] == moved) { if (cmp == null) siftUpComparable(i, moved, array); else siftUpUsingComparator(i, moved, array, cmp); } } size = n; } /** * Inserts item x at position k, maintaining heap invariant by * demoting x down the tree repeatedly until it is less than or * equal to its children or is a leaf. * 把x 元素放在 下標k的位置。經過循環降級x的位置(若是有必要),直到保證x小於等於它的任何子節點,以維持堆的結構合法性。 * @param k the position to fill * @param x the item to insert * @param array the heap array * @param n heap size */ private static <T> void siftDownComparable(int k, T x, Object[] array, int n) { if (n > 0) { Comparable<? super T> key = (Comparable<? super T>)x; int half = n >>> 1; // loop while a non-leaf 當是非葉子節點位置,才循環。 while (k < half) {//這個意思就是,若是k位置有子節點,那麼k的位置必定在數組前半部分。由於在數組中,一個元素位置爲k那麼它的左節點在2k+1位置,右節點在2k+2位置。 int child = (k << 1) + 1; // assume left child is least Object c = array[child]; int right = child + 1;//右孩子下標 if (right < n && ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)//若是右孩子小於左孩子 c = array[child = right];//獲取右孩子 //上面語句實際上是選擇左右孩子較小的一個(值和位置),寫法我學習了!! if (key.compareTo((T) c) <= 0)//若是插入值比左孩子/右孩子(較小的一個)小,就是符合二叉堆,結束循環, break; array[k] = c;//把左孩子/右孩子(較小的一個)賦值到k位置 k = child;//把左孩子/右孩子(較小的一個)的位置賦值給k,找他們的左右孩子,下輪循環。 } array[k] = key;//賦值插入值到k位置 } }