简介
在这个实验中,你将学习如何在 Java 中检查一个列表是否包含另一个列表的所有元素。在处理集合以及理解数据集之间的关系时,这是一项基本任务。
我们将探索 Java 集合框架提供的高效 containsAll()
方法,用于快速进行子集检查。为了巩固你的理解,你还将学习如何使用循环手动执行此检查。最后,我们将使用边界情况(包括空列表和 null 列表)测试这些方法的行为,以确保代码的健壮性。
在这个实验中,你将学习如何在 Java 中检查一个列表是否包含另一个列表的所有元素。在处理集合以及理解数据集之间的关系时,这是一项基本任务。
我们将探索 Java 集合框架提供的高效 containsAll()
方法,用于快速进行子集检查。为了巩固你的理解,你还将学习如何使用循环手动执行此检查。最后,我们将使用边界情况(包括空列表和 null 列表)测试这些方法的行为,以确保代码的健壮性。
containsAll()
进行子集检查在这一步中,我们将探讨如何使用 Java 中的 containsAll()
方法来检查一个列表是否是另一个列表的子集。在处理集合时,这是一项常见任务,而 containsAll()
提供了一种便捷的方式来执行此检查。
首先,在你的 ~/project
目录下创建一个名为 SubsetCheck.java
的新 Java 文件。你可以使用左侧的 WebIDE 文件资源管理器来完成此操作。在 ~/project
区域右键单击,选择“新建文件”,然后输入 SubsetCheck.java
。
现在,在编辑器中打开 SubsetCheck.java
文件,并添加以下代码:
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubset = mainList.containsAll(subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList? " + isSubset);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList
boolean isAnotherSubset = mainList.containsAll(anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList? " + isAnotherSubset);
}
}
让我们来分析一下这段代码:
java.util
包中导入 ArrayList
和 List
以处理列表。ArrayList
对象:mainList
和 subList
。mainList.containsAll(subList)
。此方法检查 mainList
是否包含 subList
中的所有元素。如果包含,则返回 true
,否则返回 false
。isSubset
中并打印出来。anotherList
,其中包含一个 mainList
中不存在的元素,并执行相同的检查,以查看当它不是子集时的结果。保存 SubsetCheck.java
文件(Ctrl+S 或 Cmd+S)。
现在,打开 WebIDE 底部的终端。确保你位于 ~/project
目录中。如果不在,请使用命令 cd ~/project
。
使用 javac
命令编译 Java 代码:
javac SubsetCheck.java
如果没有编译错误,你应该会看到 ~/project
目录中创建了一个 SubsetCheck.class
文件。
最后,使用 java
命令运行编译后的 Java 程序:
java SubsetCheck
你应该会看到类似于以下的输出:
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList? false
此输出证实了 subList
确实是 mainList
的子集,因为它的所有元素都存在于 mainList
中,而 anotherList
不是子集,因为“Grape”不在 mainList
中。
在上一步中,我们使用了便捷的 containsAll()
方法来检查子集。虽然 containsAll()
方法很高效,但了解如何使用循环手动执行此检查会很有帮助。这将加深你对集合方法内部工作原理的理解。
让我们在 SubsetCheck.java
文件中添加一个新方法,以手动执行子集检查。在 WebIDE 编辑器中打开 ~/project/SubsetCheck.java
文件。
在 SubsetCheck
类内部,但在 main
方法外部添加以下方法:
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
这个新方法 isSubsetManual
接受两个列表作为输入。然后,它会遍历 subList
中的每个 element
。在循环内部,它使用 contains()
方法检查 mainList
是否包含当前的 element
。如果在 subList
中发现哪怕有一个元素不在 mainList
中,它就会立即判定 subList
不是子集,并返回 false
。如果循环结束后,没有发现 subList
中有任何元素不在 mainList
中,就意味着所有元素都存在,该方法将返回 true
。
现在,让我们从 main
方法中调用这个新方法,将其结果与 containsAll()
的结果进行比较。修改 SubsetCheck.java
中的 main
方法,以包含对 isSubsetManual
的调用:
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubsetContainsAll = mainList.containsAll(subList);
// Check if subList is a subset of mainList using manual loop
boolean isSubsetManualCheck = isSubsetManual(mainList, subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList (containsAll)? " + isSubsetContainsAll);
System.out.println("Is subList a subset of mainList (manual check)? " + isSubsetManualCheck);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList using containsAll()
boolean isAnotherSubsetContainsAll = mainList.containsAll(anotherList);
// Check if anotherList is a subset of mainList using manual loop
boolean isAnotherSubsetManualCheck = isSubsetManual(mainList, anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList (containsAll)? " + isAnotherSubsetContainsAll);
System.out.println("Is anotherList a subset of mainList (manual check)? " + isAnotherSubsetManualCheck);
}
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
}
保存修改后的 SubsetCheck.java
文件。
现在,在终端中编译更新后的代码:
javac SubsetCheck.java
然后再次运行程序:
java SubsetCheck
你应该会看到类似以下的输出,表明 containsAll()
方法和我们的手动循环方法产生了相同的结果:
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList (containsAll)? true
Is subList a subset of mainList (manual check)? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList (containsAll)? false
Is anotherList a subset of mainList (manual check)? false
这一步表明,通过遍历潜在的子集并检查每个元素是否存在于主列表中,你可以获得与 containsAll()
相同的结果。虽然由于 containsAll()
的简洁性以及 Java 库中可能的性能优化,它通常是首选方法,但理解手动实现的方法对于学习来说是很有价值的。
在这一步中,我们将探讨 containsAll()
方法和我们的手动检查方法在处理空列表和 null
值时的表现。理解这些边界情况对于编写健壮的代码至关重要。
在 WebIDE 编辑器中打开 ~/project/SubsetCheck.java
文件。我们将在 main
方法中添加更多测试用例。
修改 main
方法,以包含对空列表和 null
列表的检查:
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubsetContainsAll = mainList.containsAll(subList);
// Check if subList is a subset of mainList using manual loop
boolean isSubsetManualCheck = isSubsetManual(mainList, subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList (containsAll)? " + isSubsetContainsAll);
System.out.println("Is subList a subset of mainList (manual check)? " + isSubsetManualCheck);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList using containsAll()
boolean isAnotherSubsetContainsAll = mainList.containsAll(anotherList);
// Check if anotherList is a subset of mainList using manual loop
boolean isAnotherSubsetManualCheck = isSubsetManual(mainList, anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList (containsAll)? " + isAnotherSubsetContainsAll);
System.out.println("Is anotherList a subset of mainList (manual check)? " + isAnotherSubsetManualCheck);
// --- Test with Empty Lists ---
// Create an empty list
List<String> emptyList = new ArrayList<>();
// Check if emptyList is a subset of mainList
boolean isEmptySubsetContainsAll = mainList.containsAll(emptyList);
boolean isEmptySubsetManualCheck = isSubsetManual(mainList, emptyList);
System.out.println("\nEmpty List: " + emptyList);
System.out.println("Is emptyList a subset of mainList (containsAll)? " + isEmptySubsetContainsAll);
System.out.println("Is emptyList a subset of mainList (manual check)? " + isEmptySubsetManualCheck);
// Check if mainList is a subset of emptyList (should be false unless mainList is also empty)
boolean isMainSubsetEmptyContainsAll = emptyList.containsAll(mainList);
boolean isMainSubsetEmptyManualCheck = isSubsetManual(emptyList, mainList);
System.out.println("Is mainList a subset of emptyList (containsAll)? " + isMainSubsetEmptyContainsAll);
System.out.println("Is mainList a subset of emptyList (manual check)? " + isMainSubsetEmptyManualCheck);
// --- Test with Null List ---
// Create a null list
List<String> nullList = null;
// Check with nullList using containsAll()
System.out.println("\nNull List: " + nullList);
try {
boolean isNullSubsetContainsAll = mainList.containsAll(nullList);
System.out.println("Is nullList a subset of mainList (containsAll)? " + isNullSubsetContainsAll);
} catch (NullPointerException e) {
System.out.println("Checking with nullList using containsAll() resulted in: " + e);
}
// Check with nullList using manual loop
try {
boolean isNullSubsetManualCheck = isSubsetManual(mainList, nullList);
System.out.println("Is nullList a subset of mainList (manual check)? " + isNullSubsetManualCheck);
} catch (NullPointerException e) {
System.out.println("Checking with nullList using manual check resulted in: " + e);
}
}
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Add a check for null subList in the manual method
if (subList == null) {
throw new NullPointerException("Sub list cannot be null for manual check.");
}
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
}
我们添加了对 emptyList
和 nullList
进行测试的部分。注意,在对 nullList
进行测试时,我们将调用语句包裹在 try-catch
块中。这是因为尝试对 null
对象调用方法(如 mainList.containsAll(nullList)
)会导致 NullPointerException
。我们的手动方法也需要处理 subList
为 null
的情况,因此我们在 isSubsetManual
方法的开头添加了一个检查。
保存修改后的 SubsetCheck.java
文件。
在终端中编译更新后的代码:
javac SubsetCheck.java
然后再次运行程序:
java SubsetCheck
你应该会看到类似以下的输出:
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList (containsAll)? true
Is subList a subset of mainList (manual check)? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList (containsAll)? false
Is anotherList a subset of mainList (manual check)? false
Empty List: []
Is emptyList a subset of mainList (containsAll)? true
Is emptyList a subset of mainList (manual check)? true
Is mainList a subset of emptyList (containsAll)? false
Is mainList a subset of emptyList (manual check)? false
Null List: null
Checking with nullList using containsAll() resulted in: java.lang.NullPointerException
Checking with nullList using manual check resulted in: java.lang.NullPointerException: Sub list cannot be null for manual check.
从输出中可以观察到以下几点:
containsAll()
方法和我们的手动方法都能正确识别这一点。null
列表传递给 containsAll()
方法或我们的手动方法(未进行空值检查)会导致 NullPointerException
。这凸显了在代码中处理潜在 null
值的重要性。这一步结束了我们对 Java 列表中子集检查的探索。你已经学会了如何使用内置的 containsAll()
方法、如何手动进行检查,以及这些方法在处理空列表和 null
列表时的表现。
在这个实验中,我们学习了如何在 Java 中检查一个列表是否包含另一个列表的所有元素。我们主要关注使用 Collection
接口提供的便捷 containsAll()
方法。
我们通过示例列表演示了如何使用 containsAll()
方法,并观察了它在子集和非子集情况下的表现。该方法为执行这种常见的列表比较任务提供了一种简洁而高效的方式。