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("这两个集合没交集");
}
//取得交集
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。足以说明,基础真的很重要。如果有描述不对的,希望各位指出,一起学习,一起进步!

猜你喜欢

转载自blog.csdn.net/weixin_41126799/article/details/87387454