Введение
В этом практическом занятии (лабораторной работе) вы научитесь проверять, содержит ли один список все элементы другого списка на Java. Это фундаментальная задача при работе с коллекциями и понимании взаимосвязей между наборами данных.
Мы рассмотрим эффективный метод containsAll(), предоставленный фреймворком Java Collections для быстрой проверки на подмножество. Чтобы закрепить ваше понимание, вы также научитесь выполнять такую проверку вручную с использованием цикла. Наконец, мы протестируем поведение этих методов на граничных случаях, включая пустые и нулевые списки, чтобы обеспечить надежность кода.
Использование метода containsAll() для проверки на подмножество
На этом этапе мы рассмотрим, как проверить, является ли один список подмножеством другого с использованием метода containsAll() в Java. Это распространенная задача при работе с коллекциями, и метод containsAll() предоставляет удобный способ для выполнения такой проверки.
Сначала создадим новый Java-файл с именем SubsetCheck.java в директории ~/project. Это можно сделать с помощью проводника файлов WebIDE слева. Щелкните правой кнопкой мыши в области ~/project, выберите "New File" (Новый файл) и введите 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);
}
}
Разберем этот код:
- Мы импортируем классы
ArrayListиListиз пакетаjava.utilдля работы со списками. - Создаем два объекта
ArrayList:mainListиsubList. - Добавляем несколько строковых элементов в оба списка.
- Основная часть - это вызов
mainList.containsAll(subList). Этот метод проверяет, содержит лиmainListвсе элементы, присутствующие вsubList. Он возвращаетtrue, если это так, иfalseв противном случае. - Результат сохраняем в булевой переменной
isSubsetи выводим на экран. - Затем создаем
anotherList, который содержит элемент, отсутствующий вmainList, и выполняем ту же проверку, чтобы увидеть результат, когда список не является подмножеством.
Сохраните файл SubsetCheck.java (Ctrl+S или Cmd+S).
Теперь откройте терминал внизу WebIDE. Убедитесь, что вы находитесь в директории ~/project. Если нет, используйте команду cd ~/project.
Скомпилируйте Java-код с помощью команды javac:
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 для ручной проверки на подмножество. Откройте файл ~/project/SubsetCheck.java в редакторе WebIDE.
Добавьте следующий метод внутри класса 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 принимает два списка в качестве входных параметров. Затем он проходит по каждому element в subList. Внутри цикла он проверяет, содержит ли mainList текущий element с использованием метода contains(). Если он находит хотя бы один элемент в subList, который не присутствует в mainList, он сразу понимает, что subList не является подмножеством и возвращает false. Если цикл завершается без нахождения элементов в subList, которых нет в mainList, это означает, что все элементы присутствуют, и метод возвращает true.
Теперь вызовем этот новый метод из нашего метода main, чтобы сравнить его результат с результатом метода containsAll(). Измените метод main в файле SubsetCheck.java, чтобы включить вызовы метода 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-библиотеке, понимание ручного подхода ценно для обучения.
Тестирование с пустыми и null-списками
На этом этапе мы рассмотрим, как метод containsAll() и наш метод ручной проверки ведут себя при работе с пустыми списками и значениями null. Понимание этих крайних случаев важно для написания надежного кода.
Откройте файл ~/project/SubsetCheck.java в редакторе WebIDE. Мы добавим больше тестовых случаев в метод 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) и списком со значением null (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()или наш метод ручной проверки (без проверки наnull) приводит к исключениюNullPointerException. Это подчеркивает важность обработки потенциальных значенийnullв вашем коде.
Этот этап завершает наше исследование проверки на подмножество в списках Java. Вы узнали, как использовать встроенный метод containsAll(), как выполнить проверку вручную и как эти методы ведут себя с пустыми и нулевыми списками.
Резюме
В этом практическом занятии (лабораторной работе) мы научились проверять, содержит ли один список все элементы другого списка на Java. Мы в основном сосредоточились на использовании удобного метода containsAll(), предоставляемого интерфейсом Collection.
Мы показали, как использовать метод containsAll() на примерах списков и изучили его поведение в случаях, когда один список является подмножеством другого, а также когда это не так. Этот метод представляет собой лаконичный и эффективный способ выполнения этой распространенной задачи сравнения списков.



