王小锤学Java:retainAll函数那点儿事

640?wx_fmt=jpeg

王小锤是一家电商网站的Java程序员,下午刚打开电脑,公司的运营妹子小美就过来找他:“小锤,你能帮我导一份数据吗?我需要昨天成为SVIP用户,并且之前给过差评的这些账号,不过要把一个叫大宝的账号去掉,他老板亲戚。”对于小美的需求,小锤从来没有拒绝过,这次也不例外。

答应小美之后,小锤心想,这么简单的事情,一个SQL就搞定了。小美又要夸我效率高了,想想还有点小激动呢。小锤打开电脑的一瞬间整个人都不好了。原来今天早上下班前,他才刚刚完成微服务的拆分。现在订单和用户已经分成了两个服务,评价表和用户等级表也已经在两个数据库里了。这就尴尬了,本来一个SQL能解决的事情,现在还需要跨服务调接口了。

不过小锤马上就有思路了:

640?wx_fmt=png
小锤的思路

有了思路之后,小锤立刻就开始写代码了。

两分钟后……新鲜的代码出炉了(这里给个类似的Demo)。

 1public class NoBadReviewSVIP {
 2    public static void main(String[] args) {
 3        String[] svipArr = new String[]{"大宝","凉凉","Tom"};
 4        String[] badReviewUserArr = new String[]{"凉凉","Tom","大宝","小锤"};
 5        List<String> svips = new ArrayList<String>(Arrays.asList(svipArr));//从用户服务查
 6        svips.remove("大宝");
 7        List<String> badReviewUsers = new ArrayList<String>(Arrays.asList(badReviewUserArr));//从订单服务查
 8        if (svips.retainAll(badReviewUsers)) {
 9            System.out.println(svips);
10            System.out.println("有交集");
11        } else {
12            System.out.println("没有交集,告诉小美");
13        }
14    }
15}

小锤先运行了一下,发现结果是没有交集,于是小锤告诉小美:“没有你要的用户,昨天新的SVIP都没有给过差评。”小美说:“不可能,老板说有一个叫Tom的用户就给了差评,你再好好查查。”

小锤一查发现Tom真的给了差评,而且昨天刚刚成为SVIP。到底是哪里出了问题呢?小锤对着代码看了一个多小时也没发现问题,于是向身边的大锤请教。大锤只看了一眼,告诉他if的条件不对,让他看retainAll的具体实现。

retainAll的实现

于是小锤就开始看retainAll的源码了,发现它调用了一个batchRemove的私有方法。

 1    private boolean batchRemove(Collection<?> c, boolean complement) {
 2        final Object[] elementData = this.elementData;
 3        //w表示两个list的公共元素个数
 4        int r = 0, w = 0;
 5        boolean modified = false;
 6        try {
 7            for (; r < size; r++)
 8                //如果有公共元素,存入elementData
 9                if (c.contains(elementData[r]) == complement)
10                    elementData[w++] = elementData[r];
11        } finally {
12            // c.contains()抛异常,就把剩余元素复制到elementData
13            if (r != size) {
14                System.arraycopy(elementData, r,
15                                 elementData, w,
16                                 size - r);
17                //此时w为调用方list的长度
18                w += size - r;
19            }
20            //如果元素数量改变
21            if (w != size) {
22                // 多余空间教给GC
23                for (int i = w; i < size; i++)
24                    elementData[i] = null;
25                //记录list修改的次数
26                modCount += size - w;
27                //重新设置list大小
28                size = w;
29                //返回true
30                modified = true;
31            }
32        }
33        return modified;
34    }

这么一看小锤就明白了,对于

1listA.retainAll(listB)

listA中保存了listA和listB的交集,如果listA中元素数量改变,那么就返回true;如果listA的元素不变,则返回false。

也就是说,判断两个list是否有交集,只需要执行上述代码,然后判断listA的size是否大于0就可以了。

想通了这一点,小锤马上修改了代码,重新运行,得到正确结果,并且把结果告诉了小美。

万万没想到,小锤最后仍然没有得到小美的夸奖,因为所有的SVIP都给了差评,小美要负责挨个询问原因并且帮助他们解决问题,所以根本没有时间搭理小锤。

日常自黑
640?wx_fmt=jpeg
斐波那契程序员

留言请移步博客,或者点击阅读原文

https://jackeyzhe.github.io/2019/03/13/retainAll%E5%87%BD%E6%95%B0%E9%82%A3%E7%82%B9%E5%84%BF%E4%BA%8B/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值