Java中取多个集合的交集——retainAll()

Java中取多个集合的交集

集合 Collection 接口中定义了 retainAll()方法

retainAll()

Retains only the elements in this set that are contained in the specified collection (optional operation). In other words, removes from this set all of its elements that are not contained in the specified collection. If the specified collection is also a set, this operation effectively modifies this set so that its value is the intersection of the two sets.

简单来说,该方法目的是取当前集合参数指定集合的一个交集,并修改当前集合,仅保留交集元素。

下图是集合类框架的一个架构图:
在这里插入图片描述

通过这个架构图,可以在大脑中对集合这块的类有个清晰的定位。

抽象类 AbstractCollection 中对 retainAll() 方法进行了实现。
使用Set集合的 retainAll() 方法,其实就是调用了AbstractCollection中的 retainAll()方法。

其底层其实使用的 contains() 方法进行判断元素是否存在集合中。对于当前集合中的元素进行遍历,判断每个元素是否存在于参数集合中,若不存在则从当前集合中移除该元素,最终保留的就是两个集合共有的元素。

public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

对于 ArrayList 类,对 retainAll() 方法进行了重写。其中的核心思路是一样的。

public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

对于多个集合取交集(不确定集合的个数)

思路:
创建一个新的 List 集合,将目标集合都放入新创建的 List 集合中,若有条件过滤,可使用stream流进行条件筛选(比如去掉空集合),最终得到结果 List 集合。
然后遍历该集合,使用集合中的第一个集合依次和后续的每个集合取交集,即可得到所有集合的交集。

Set set1 = new HashSet();
Set set2 = new HashSet();
Set set3 = new HashSet();

set1.add("1");
set2.add("1");
set2.add("2");
set3.add("1");

List<Set> setList = new ArrayList<>();
setList.add(set1);
setList.add(set2);
setList.add(set3);

//List<Set> resultSetList = setList.stream().filter(Objects::nonNull).collect(Collectors.toList());

Set resultSet = setList.get(0);
resultSetList.forEach(item -> {
    resultSet.retainAll(item);
});

//resultSet 结果仅包含 1

再复杂的东西都是由简单的东西组成的,只因量变达到质变。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值