Apex裏面的retainAll

Apex裏面的retainAll

學習目的
1,掌握集合retainAll的用法
2,避免幽靈bug

集合retainAll的用法

1,Boolean retainAll(List/Set)
該方法的作用相信很多人會認爲是兩個集合取交集。那真的是這樣嗎?在揭曉謎底之前,先來幾道題目。

Set<String> cmpPartnerTypeSet = new Set<String>{'A','B'}; 
Set<String> cmpincentivePagramSet = new Set<String>{'A','B'};  
System.debug('===='+cmpPartnerTypeSet.retainAll(cmpincentivePagramSet));

輸出:false

在這裏插入圖片描述
這個時候肯定心裏會說上一句:Fuck!預期的true呢?
那再來一道題目:

Set<String> cmpPartnerTypeSet = new Set<String>{'A','B'}; 
Set<String> cmpincentivePagramSet = new Set<String>{'B'};  
System.debug('===='+cmpPartnerTypeSet.retainAll(cmpincentivePagramSet));

輸出:true
在這裏插入圖片描述
好像又對了,有交集返回true。沒毛病。
這個時候開始質疑,我擦擦,是不是編譯器壞了啊。玩我啊!
再來一道,試試:

Set<String> cmpPartnerTypeSet = new Set<String>{'A','B'}; 
Set<String> cmpincentivePagramSet = new Set<String>{'A','B','C'};  
System.debug('===='+cmpPartnerTypeSet.retainAll(cmpincentivePagramSet));

輸出:false
在這裏插入圖片描述
這~~~~~,玩我啊!
別急,我們繼續玩:

Set<String> cmpPartnerTypeSet = new Set<String>{'A','B'}; 
Set<String> cmpincentivePagramSet = new Set<String>{'D','B','C'};  
System.debug('===='+cmpPartnerTypeSet.retainAll(cmpincentivePagramSet));

輸出:true
在這裏插入圖片描述
到這裏有沒有發現一個問題,就是他丫的根本不是一個正宗的取交集的函數。現在我們去看看它的真面目:

public boolean retainAll(Collection<?> c) {
        //調用自己的私有方法
        return batchRemove(c, true);
    }
//集合A比較與集合B的交集
 private boolean batchRemove(Collection<?> c, boolean complement) {
             //獲得當前對象的所有元素
            final Object[] elementData = this.elementData;
            //w:標記兩個集合公共元素的個數
            int r = 0, w = 0;
            //設置標誌位
            boolean modified = false;
            try {
                //遍歷集合A
                for (; r < size; r++)
                    //判斷集合B中是否包含集合A中的當前元素
                    if (c.contains(elementData[r]) == complement)
                        //如果包含則直接保存。
                        elementData[w++] = elementData[r];
            } finally {
                // 如果 c.contains() 拋出異常
                if (r != size) {
                    //複製剩餘的元素
                    System.arraycopy(elementData, r,
                                     elementData, w,
                                     size - r);
                    //w爲當前集合A的length
                    w += size - r;
                }
                //如果集合A的大小放生改變
                if (w != size) {
                    // 清除工作
                    for (int i = w; i < size; i++)
                        elementData[i] = null;
                    //記錄集合中元素的改變(add/remove)
                    modCount += size - w;
                    //設置當前數組的大小
                    size = w;
                    //返回爲true
                    modified = true;
                }
            }
            return modified;
        }

看到這裏就明白了,這丫的原來就不能直接用來判斷是否有交集。我們通過上面發現,當A.retainAll(B) 時,A集合發生改變的時候,返回的就是true,而A沒有發生改變,結果就是false。

不過retainAll確實可以用來判斷兩個集合是不是有交集。使用方法如下:

Set<String> A= new Set<String>{'A','B'}; 
Set<String> B= new Set<String>{'D','B','C'};  
A.retainAll(B);//來一發
if(A.size() > 0){
	System.debug("這兩個集合有交集");
}else{
	System.debug("這兩個集合沒交集");
}

好了,這個是今天在寫代碼碰見的一個bug。足以說明,基礎真的很重要。如果有描述不對的,希望各位指出,一起學習,一起進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章