瞬间教你学会使用java中list的retainAll方法

简介: 当我们有两个list集合的时候,我们可以使用retainAll方法求得两个list集合的子集。retainAll是Collection接口中提供的一个方法,各个实现类有自己的实现方式,我们这里介绍ArrayList的实现方式。

retainAll方法简介

当我们有两个list集合的时候,我们可以使用retainAll方法求得两个list集合的子集。retainAll是Collection接口中提供的一个方法,各个实现类有自己的实现方式,我们这里介绍ArrayList的实现方式。

retainAll源码深入

可以看到collection接口中的retainAll方法,需要传入一个集合。

boolean retainAll(Collection<?> c);

进入arrayList的方法实现。可以看到如下代码:

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

由以上代码可知,传入的集合不能为null。接下来看看batchRemove方法。

    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;
    }

我们看到上述方法的流程如下:
首先获得当前对象的所有元素,然后通过r和w变量标记两个集合公共元素的个数。初始化标志位为false。然后进入循环遍历当前集合,如果传入的集合中包含当前集合的元素,就直接将这个元素保存下来。最后到finally块中,如果r不等于size,证明在循环的过程中出现了异常,然后将剩余的元素进行复制,重新计算数组的剩余元素值。如果剩余的元素值不等于size,则将多余的位置进行清空。更改modcount的值。这个modcount是父类abstarctlist的值,初始值为0,集合中的内容没修改一次则增加1。最后重新设置size的大小。返回是否修改值。

retainAll返回值的说明

这里有两个说明。
第一个:如果集合A数组的大小没有改变,则返回false。如果集合A和集合B是完全相同的集合,也会返回false。

public static void main(String[] args) {
        ArrayList<String> list1= new ArrayList<String>();
        list1.add("123");
        ArrayList<String> list2= new ArrayList<String>();
        list2.add("123");
        System.out.println(list1.retainAll(list2)); 
    }

如上代码会返回false。
第二个:两个集合没有交集,会返回true。

public static void main(String[] args) {
        ArrayList<String> list1= new ArrayList<String>();
        list1.add("123");
        ArrayList<String> list2= new ArrayList<String>();
        list2.add("12345");
        System.out.println(list1.retainAll(list2));
    }

如上代码会返回true。
总结:当集合A的大小改变的时候返回的是True,大小没有改变的时候返回的是False。

retainAll的判断方法

public static void main(String[] args) {
        ArrayList<String> list1= new ArrayList<String>();
        list1.add("123");
        ArrayList<String> list2= new ArrayList<String>();
        list2.add("123");
        list1.retainAll(list2);
        if(list1.size()>0){
            System.out.println("有交集");
        }else{
            System.out.println("没有交集");
        }
    }

通过判断集合的大小,来确定是否存在交集。不能通过方法返回的True和False来判断。

retainAll的实际效果使用

我们声明两个集合,通过调用retainAll,保留两个集合的交集。最后再看输出的效果。

    public static void main(String[] args) {
        Collection collection1 = new ArrayList();
        collection1.add("a");
        collection1.add("b");
        collection1.add("c");
        Collection collection2 = new ArrayList();
        collection2.add("ab");
        collection2.add("abc");
        collection2.add('a');
        System.out.println(collection1);
        boolean flag = collection1.retainAll(collection2);
        System.out.println(flag);
        System.out.println(collection1);
    }

执行结果如下:

[a, b, c]
true
[a]

保留了两个结合的交集。

总结

list的retainAll方法的介绍和分析到此结束,文中难免有不足之处,望大家指正交流。

相关文章
|
5天前
|
Java 数据处理 数据安全/隐私保护
Java处理数据接口方法
Java处理数据接口方法
15 1
|
2月前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
48 17
|
23天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
76 4
|
27天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
72 2
|
2月前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
60 5
|
2月前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
29 3
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
20 3
|
2月前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
2月前
|
Java 程序员
Java|List.subList 踩坑小记
不应该仅凭印象和猜测,就开始使用一个方法,至少花一分钟认真读完它的官方注释文档。
23 1
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
19 2