Java【代码分享 12】判断一个集合是否包含另一个集合中的一个或多个元素 retainAll() 及其他方法

简介: Java【代码分享 12】判断一个集合是否包含另一个集合中的一个或多个元素 retainAll() 及其他方法

1.原因说明

业务中有这么一个逻辑:判断第一个集合里包含第二个集合中的一个或多个元素。首先想到的是 contains() 但是它的参数只能传 Object,还有另一个也就是 retainAll() 它可以传 Collection<?>

2.代码测试

public class TestRetainAll {
    public static void main(String[] args) {
        // 创建一个集合
        ArrayList<String> one = new ArrayList<>();
        one.add("a");
        one.add("b");
        one.add("c");
        System.out.println("ArrayList 1: " + one);
        // 创建另一个集合
        ArrayList<String> other = new ArrayList<>();
        other.add("a");
        other.add("b");
        other.add("d");
        System.out.println("ArrayList 2: " + other);
        // 前者是否包含后者某个元素
        boolean isContains = isContainsOne(one, other);
        System.out.println("ArrayList 1: " + one + " ; isContains:" + isContains);
        // 使用retainAll运算后
        boolean isRetainAll = one.retainAll(other);
        System.out.println("ArrayList 1: " + one + " ; isRetainAll:" + isRetainAll);
    }
    /**
     * 前者是否包含后者某个元素
     *
     * @param oneList   第一个集合
     * @param otherList 第二个集合
     * @return 是否包含
     */
    private static boolean isContainsOne(ArrayList<String> oneList, ArrayList<String> otherList) {
        for (String one : otherList) {
            boolean contains = oneList.contains(one);
            if (contains) {
                return true;
            }
        }
        return false;
    }
}

运行结果:

ArrayList 1: [a, b, c]
ArrayList 2: [a, b, d]
ArrayList 1: [a, b, c] ; isContains:true
ArrayList 1: [a, b] ; isRetainAll:true

3.总结

retainAll 方法:

Retains only the elements in this list that are contained in the specified collection. In other words, removes from this list all of its elements that are not contained in the specified collection.

只保留此列表中包含在指定集合中的元素。换句话说,从该列表中删除指定集合中不包含的所有元素。我看一下源码:

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

实际上就是求交集,但是交集的结果放在了第一个集合里,如果后续还要使用第一个集合就会有影响,而且 retainAll 的返回值说明的是 是否删除了元素 我们可以看下边的两个例子:

ArrayList 1: [a, b, c]
ArrayList 2: [e, f, g]
ArrayList 1: [a, b, c] ; isContains:false
ArrayList 1: [] ; isRetainAll:true
ArrayList 1: [a, b, c]
ArrayList 2: [a, b, c]
ArrayList 1: [a, b, c] ; isContains:true
ArrayList 1: [a, b, c] ; isRetainAll:false

由此看来 retainAll 的返回值是无法满足 判断一个集合是否包含另一个集合中的一个或多个元素 这个逻辑的,原因是:

  • 全部包含返回值为false
  • 部分包含返回值为true
  • 不包含返回值也是true

所有只能使用 isContainsOne 方法。

目录
相关文章
|
18小时前
|
存储 缓存 监控
如何优化你的Java代码性能
如何优化你的Java代码性能
|
1天前
|
Java
Java自定义注解:优雅的代码标记
Java自定义注解:优雅的代码标记
9 1
|
21小时前
|
存储 安全 Java
探索JAVA泛型:让代码在编译时就拥有金钟罩铁布衫!
【6月更文挑战第28天】Java泛型,自1.5版起,是代码安全性的守护者。它允许在类、接口和方法中使用类型参数,减少重复代码,提升可读性。泛型在编译时执行类型检查,防止运行时类型错误,如同给代码穿上“金钟罩铁布衫”。以Box类为例,泛型避免了显式转换,确保类型安全,让编程更加高效和无忧。
|
22小时前
|
存储 前端开发 Java
Java 代码执行的原理解读
Java 代码执行的原理解读
|
1天前
|
设计模式 Java 开发者
Java中的代码优雅重构实战
Java中的代码优雅重构实战
|
1天前
|
存储 安全 Java
那些年,JAVA 泛型如何守护我们的代码梦?
【6月更文挑战第28天】Java 泛型,编程旅途的守护者,提升代码安全与效率。从繁琐的类型转换中解放,如列表示例所示,泛型简化了元素操作。自定义泛型类增强复用性,确保数据结构一致性,避免潜在错误。泛型,如同严谨的卫士,保障系统稳定,伴随开发者成长,铸就优雅、高效的代码世界。
|
1天前
|
存储 安全 Java
JAVA泛型大揭秘:如何在编译时守护你的代码安全?
【6月更文挑战第28天】Java泛型是JDK 5引入的特性,用于提升代码复用和类型安全性。通过类型参数如`&lt;T&gt;`,泛型在编译时确保数据类型的正确性。例如,泛型类`GenericList&lt;T&gt;`允许创建特定类型的列表,如`GenericList&lt;String&gt;`,阻止了不兼容类型元素的添加,防止运行时ClassCastException。泛型方法如`swap()`也确保了操作的类型安全,增强了代码的可读性和维护性。
|
3天前
|
Java 机器人 程序员
Java中的线程通信:wait、notify与Condition详解
Java中的线程通信:wait、notify与Condition详解
|
3天前
|
存储 安全 Java
Java中的线程安全与同步技术
Java中的线程安全与同步技术
|
2天前
|
监控 Java 调度
Java并发编程:深入理解线程池
【6月更文挑战第26天】在Java并发编程的世界中,线程池是提升应用性能、优化资源管理的关键组件。本文将深入探讨线程池的内部机制,从核心概念到实际应用,揭示如何有效利用线程池来处理并发任务,同时避免常见的陷阱和错误实践。通过实例分析,我们将了解线程池配置的策略和对性能的影响,以及如何监控和维护线程池的健康状况。
7 1