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。足以說明,基礎真的很重要。如果有描述不對的,希望各位指出,一起學習,一起進步!