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("这两个集合没交集");
}
//取得交集
Set<String> cmpPartnerTypeSet = new Set<String>{'B'};
Set<String> cmpincentivePagramSet = new Set<String>{'A'};
cmpPartnerTypeSet.retainAll(cmpincentivePagramSet);
System.debug('===='+cmpPartnerTypeSet.size());
for (String s: cmpPartnerTypeSet) {
System.debug('======='+s);
}
好了,这个是今天在写代码碰见的一个bug。足以说明,基础真的很重要。如果有描述不对的,希望各位指出,一起学习,一起进步!