如何在 Java 中检查一个集合是否包含另一个集合的所有元素

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,你将学习如何在 Java 中检查一个集合是否包含另一个集合的所有元素。我们将探讨 containsAll() 方法,这是一种执行子集检查的便捷方式。

通过实际操作的示例,你将学习如何在不同的集合类型中使用 containsAll() 方法,以及如何处理空集合和空引用(null)集合等边界情况。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/DataStructuresGroup -.-> java/arrays_methods("Arrays Methods") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("Exceptions") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/linkedlist("LinkedList") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/hashset("HashSet") subgraph Lab Skills java/arrays_methods -.-> lab-559974{{"如何在 Java 中检查一个集合是否包含另一个集合的所有元素"}} java/collections_methods -.-> lab-559974{{"如何在 Java 中检查一个集合是否包含另一个集合的所有元素"}} java/exceptions -.-> lab-559974{{"如何在 Java 中检查一个集合是否包含另一个集合的所有元素"}} java/linkedlist -.-> lab-559974{{"如何在 Java 中检查一个集合是否包含另一个集合的所有元素"}} java/hashset -.-> lab-559974{{"如何在 Java 中检查一个集合是否包含另一个集合的所有元素"}} end

使用 containsAll() 进行子集检查

在这一步中,我们将探讨如何使用 Java 中的 containsAll() 方法来检查一个集合是否是另一个集合的子集。在处理集合时,这是一项常见的操作,而 containsAll() 提供了一种便捷的方式来执行此检查。

首先,在你的 ~/project 目录下创建一个名为 SubsetCheck.java 的新 Java 文件。你可以通过在左侧的文件资源管理器中右键单击,选择“新建文件”,然后输入 SubsetCheck.java 来完成此操作。

现在,在编辑器中打开 SubsetCheck.java 文件,并添加以下代码:

import java.util.HashSet;
import java.util.Set;

public class SubsetCheck {

    public static void main(String[] args) {
        // Create the main set
        Set<Integer> mainSet = new HashSet<>();
        mainSet.add(1);
        mainSet.add(2);
        mainSet.add(3);
        mainSet.add(4);
        mainSet.add(5);

        // Create a potential subset
        Set<Integer> subset = new HashSet<>();
        subset.add(2);
        subset.add(4);

        // Check if 'subset' is a subset of 'mainSet'
        boolean isSubset = mainSet.containsAll(subset);

        // Print the result
        System.out.println("Main Set: " + mainSet);
        System.out.println("Subset: " + subset);
        System.out.println("Is 'subset' a subset of 'mainSet'? " + isSubset);
    }
}

让我们来分析一下这段代码:

  • import java.util.HashSet;import java.util.Set;:这两行代码导入了处理集合所需的类。
  • Set<Integer> mainSet = new HashSet<>();:这行代码创建了一个名为 mainSetHashSet,用于存储整数值。
  • mainSet.add(...):这些代码行向 mainSet 中添加元素。
  • Set<Integer> subset = new HashSet<>();:这行代码创建了另一个名为 subsetHashSet
  • subset.add(...):这些代码行向 subset 中添加元素。
  • boolean isSubset = mainSet.containsAll(subset);:这是此步骤的核心。调用 mainSetcontainsAll() 方法,并将 subset 作为参数传入。如果 mainSet 包含 subset 的所有元素,则返回 true,否则返回 false
  • System.out.println(...):这些代码行将集合和子集检查的结果打印到控制台。

保存 SubsetCheck.java 文件(使用 Ctrl+S 或 Cmd+S)。

现在,打开 WebIDE 底部的终端。确保你位于 ~/project 目录下。如果不是,请使用命令 cd ~/project

使用 javac 命令编译 Java 代码:

javac SubsetCheck.java

如果没有错误,你应该看不到任何输出。这意味着编译成功,并且已经创建了一个 SubsetCheck.class 文件。

最后,使用 java 命令运行编译后的 Java 程序:

java SubsetCheck

你应该会看到类似于以下的输出:

Main Set: [1, 2, 3, 4, 5]
Subset: [2, 4]
Is 'subset' a subset of 'mainSet'? true

此输出证实了 containsAll() 方法正确地识别出 subset 确实是 mainSet 的子集。

使用不同的集合类型进行测试

在上一步中,我们使用 HashSet 演示了 containsAll() 方法。Java 为 Set 接口提供了不同的实现,例如 HashSetLinkedHashSetTreeSet。虽然它们具有不同的内部结构和特性(如元素顺序),但 containsAll() 方法在这些实现中都能一致地工作。

在这一步中,我们将修改 SubsetCheck.java 文件,以使用不同类型的集合来测试 containsAll() 方法。

在 WebIDE 编辑器中打开 SubsetCheck.java 文件。

将现有代码替换为以下内容:

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class SubsetCheck {

    public static void main(String[] args) {
        // Create a main set using HashSet
        Set<Integer> hashMainSet = new HashSet<>();
        hashMainSet.add(10);
        hashMainSet.add(20);
        hashMainSet.add(30);
        hashMainSet.add(40);

        // Create a subset using LinkedHashSet
        Set<Integer> linkedSubset = new LinkedHashSet<>();
        linkedSubset.add(30);
        linkedSubset.add(10);

        // Create another subset using TreeSet
        Set<Integer> treeSubset = new TreeSet<>();
        treeSubset.add(40);
        treeSubset.add(20);

        // Check subset relationship using containsAll()
        boolean isLinkedSubset = hashMainSet.containsAll(linkedSubset);
        boolean isTreeSubset = hashMainSet.containsAll(treeSubset);

        // Create a subset that is NOT a subset
        Set<Integer> notSubset = new HashSet<>();
        notSubset.add(20);
        notSubset.add(50); // 50 is not in hashMainSet

        boolean isNotSubset = hashMainSet.containsAll(notSubset);


        // Print the results
        System.out.println("Hash Main Set: " + hashMainSet);
        System.out.println("Linked Subset: " + linkedSubset);
        System.out.println("Is Linked Subset a subset of Hash Main Set? " + isLinkedSubset);
        System.out.println("Tree Subset: " + treeSubset);
        System.out.println("Is Tree Subset a subset of Hash Main Set? " + isTreeSubset);
        System.out.println("Not Subset: " + notSubset);
        System.out.println("Is Not Subset a subset of Hash Main Set? " + isNotSubset);
    }
}

在这段更新后的代码中:

  • 我们导入了 LinkedHashSetTreeSet
  • 我们使用 HashSet 创建了 hashMainSet
  • 我们使用 LinkedHashSet 创建了 linkedSubset,使用 TreeSet 创建了 treeSubset。注意,添加到 linkedSubset 中的元素顺序与它们在 hashMainSet 中出现的顺序不同,但 containsAll() 仍然能正确工作。TreeSet 会自动对元素进行排序。
  • 我们还添加了一个 notSubset 来演示 containsAll() 返回 false 的情况。

保存 SubsetCheck.java 文件。

现在,在终端中编译修改后的代码:

javac SubsetCheck.java

如果编译成功,运行程序:

java SubsetCheck

你应该会看到类似于以下的输出:

Hash Main Set: [40, 10, 20, 30]
Linked Subset: [30, 10]
Is Linked Subset a subset of Hash Main Set? true
Tree Subset: [20, 40]
Is Tree Subset a subset of Hash Main Set? true
Not Subset: [50, 20]
Is Not Subset a subset of Hash Main Set? false

这表明,只要主集合包含子集的所有元素,containsAll() 方法就能正确工作,而不受子集所使用的具体 Set 实现的影响。

处理空集合和 null 集合

在这最后一步中,我们将研究 containsAll() 方法在处理空集合和 null 值时的行为。理解这些边界情况对于编写健壮的代码至关重要。

在 WebIDE 编辑器中打开 SubsetCheck.java 文件。

将现有代码替换为以下内容:

import java.util.HashSet;
import java.util.Set;

public class SubsetCheck {

    public static void main(String[] args) {
        Set<Integer> mainSet = new HashSet<>();
        mainSet.add(1);
        mainSet.add(2);
        mainSet.add(3);

        // Case 1: Checking with an empty set
        Set<Integer> emptySet = new HashSet<>();
        boolean isEmptySubset = mainSet.containsAll(emptySet);
        System.out.println("Main Set: " + mainSet);
        System.out.println("Empty Set: " + emptySet);
        System.out.println("Is Empty Set a subset of Main Set? " + isEmptySubset);

        System.out.println("---"); // Separator

        // Case 2: Checking if an empty set contains all elements of a non-empty set
        Set<Integer> anotherEmptySet = new HashSet<>();
        Set<Integer> nonEmptySet = new HashSet<>();
        nonEmptySet.add(1);
        boolean isEmptyContainingNonEmpty = anotherEmptySet.containsAll(nonEmptySet);
        System.out.println("Another Empty Set: " + anotherEmptySet);
        System.out.println("Non-Empty Set: " + nonEmptySet);
        System.out.println("Is Another Empty Set a subset of Non-Empty Set? " + isEmptyContainingNonEmpty);

        System.out.println("---"); // Separator

        // Case 3: Checking with a null set
        Set<Integer> nullSet = null;
        try {
            boolean isNullSubset = mainSet.containsAll(nullSet);
            System.out.println("Is Null Set a subset of Main Set? " + isNullSubset);
        } catch (NullPointerException e) {
            System.out.println("Checking with a null set resulted in a: " + e.getClass().getName());
        }
    }
}

让我们来看看新增的部分:

  • 情况 1:使用空集合进行检查:我们创建了一个 emptySet,并检查 mainSet 是否包含其所有元素。空集合被认为是任何集合的子集,包括另一个空集合。
  • 情况 2:检查空集合是否包含非空集合的所有元素:我们检查 anotherEmptySet 是否包含 nonEmptySet 的所有元素。这应该返回 false,因为空集合不包含元素 1
  • 情况 3:使用 null 集合进行检查:我们将一个 Set 变量设置为 null。尝试使用 null 参数调用 containsAll() 会导致 NullPointerException。我们使用 try-catch 块来优雅地处理这个预期的异常,并打印一条消息。

保存 SubsetCheck.java 文件。

在终端中编译代码:

javac SubsetCheck.java

运行编译后的程序:

java SubsetCheck

你应该会看到类似于以下的输出:

Main Set: [1, 2, 3]
Empty Set: []
Is Empty Set a subset of Main Set? true
---
Another Empty Set: []
Non-Empty Set: [1]
Is Another Empty Set a subset of Non-Empty Set? false
---
Checking with a null set resulted in a: java.lang.NullPointerException

此输出证实了 containsAll() 方法在处理空集合和 null 集合时的行为:

  • 空集合始终是另一个集合的子集(返回 true)。
  • 非空集合永远不会是一个空集合的子集(返回 false)。
  • null 传递给 containsAll() 会导致 NullPointerException

理解这些情况有助于你在 Java 中处理集合时避免潜在的错误。

总结

在这个实验中,我们学习了如何在 Java 中使用 containsAll() 方法来检查一个集合是否包含另一个集合的所有元素。我们首先使用 HashSet 创建了一个基础示例,以演示 containsAll() 的核心功能。该方法提供了一种直接的方式来确定一个潜在的子集是否确实包含在一个更大的集合中。

接着,我们探索了如何使用不同类型的集合来测试这一功能,了解到 containsAll() 在各种 Set 实现中都能一致地工作。最后,我们讨论了在进行子集检查时处理空集合和 null 集合的重要注意事项,以确保代码的健壮性和无错误性。