Как проверить, содержит ли список все элементы другого списка на Java

JavaJavaBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом практическом занятии (лабораторной работе) вы научитесь проверять, содержит ли один список все элементы другого списка на Java. Это фундаментальная задача при работе с коллекциями и понимании взаимосвязей между наборами данных.

Мы рассмотрим эффективный метод containsAll(), предоставленный фреймворком Java Collections для быстрой проверки на подмножество. Чтобы закрепить ваше понимание, вы также научитесь выполнять такую проверку вручную с использованием цикла. Наконец, мы протестируем поведение этих методов на граничных случаях, включая пустые и нулевые списки, чтобы обеспечить надежность кода.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java/BasicSyntaxGroup -.-> java/for_loop("For Loop") java/DataStructuresGroup -.-> java/arrays_methods("Arrays Methods") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("ArrayList") subgraph Lab Skills java/for_loop -.-> lab-559946{{"Как проверить, содержит ли список все элементы другого списка на Java"}} java/arrays_methods -.-> lab-559946{{"Как проверить, содержит ли список все элементы другого списка на Java"}} java/collections_methods -.-> lab-559946{{"Как проверить, содержит ли список все элементы другого списка на Java"}} java/classes_objects -.-> lab-559946{{"Как проверить, содержит ли список все элементы другого списка на Java"}} java/arraylist -.-> lab-559946{{"Как проверить, содержит ли список все элементы другого списка на Java"}} end

Использование метода 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-библиотеке, понимание ручного подхода ценно для обучения.

Тестирование с пустыми и нулевыми списками

На этом этапе мы рассмотрим, как метод 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() на примерах списков и изучили его поведение в случаях, когда один список является подмножеством другого, а также когда это не так. Этот метод представляет собой лаконичный и эффективный способ выполнения этой распространенной задачи сравнения списков.