JDK PriorityBlockingQueue remove(Object o) 源碼分析

分類:IT技術 時間:2017-03-25

先知道PriorityBlockingQueue 是利用數組存儲二叉堆實現。最小值(最優先)放在queue[0]位置。

//刪除某個元素
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位置
        }
    }

 


Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad