Как проверить, отсортирован ли список на Java

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

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

Введение

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

Затем вы узнаете, как использовать возможности Java Stream API для более компактного и потенциально более эффективного способа проверки сортировки. Наконец, мы рассмотрим, как обрабатывать разные порядки сортировки, такие как по возрастанию и по убыванию, чтобы сделать ваши проверки сортировки более гибкими.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/FileandIOManagementGroup(["File and I/O Management"]) java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java/BasicSyntaxGroup -.-> java/for_loop("For Loop") java/DataStructuresGroup -.-> java/arrays("Arrays") java/DataStructuresGroup -.-> java/sorting("Sorting") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("ArrayList") java/FileandIOManagementGroup -.-> java/stream("Stream") subgraph Lab Skills java/for_loop -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} java/arrays -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} java/sorting -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} java/collections_methods -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} java/arraylist -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} java/stream -.-> lab-559950{{"Как проверить, отсортирован ли список на Java"}} end

Сравнение соседних элементов списка

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

Сначала создадим новый Java-файл с именем ListComparison.java в директории ~/project. Вы можете сделать это с помощью проводника файлов WebIDE слева. Щелкните правой кнопкой мыши в области ~/project, выберите "New File" и введите ListComparison.java.

Теперь откройте файл ListComparison.java в редакторе и добавьте следующий код:

import java.util.ArrayList;
import java.util.List;

public class ListComparison {

    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(3);
        numbers.add(2);
        numbers.add(4);
        numbers.add(5);

        System.out.println("Original list: " + numbers);

        // Loop through the list, comparing adjacent elements
        for (int i = 0; i < numbers.size() - 1; i++) {
            Integer currentElement = numbers.get(i);
            Integer nextElement = numbers.get(i + 1);

            System.out.println("Comparing " + currentElement + " and " + nextElement);

            if (currentElement < nextElement) {
                System.out.println(currentElement + " is less than " + nextElement);
            } else if (currentElement > nextElement) {
                System.out.println(currentElement + " is greater than " + nextElement);
            } else {
                System.out.println(currentElement + " is equal to " + nextElement);
            }
        }
    }
}

Разберем этот код:

  • import java.util.ArrayList; и import java.util.List;: Эти строки импортируют необходимые классы для работы со списками на Java.
  • List<Integer> numbers = new ArrayList<>();: Эта строка создает новый список с именем numbers, который может хранить объекты типа Integer (целые числа).
  • numbers.add(...): Эти строки добавляют элементы в наш список.
  • for (int i = 0; i < numbers.size() - 1; i++): Это цикл for, который перебирает элементы списка. Обратите внимание, что условие цикла - i < numbers.size() - 1. Это важно, потому что мы сравниваем numbers.get(i) с numbers.get(i + 1). Если бы мы перебирали до numbers.size(), на последней итерации i + 1 вышел бы за границы списка.
  • Integer currentElement = numbers.get(i);: Эта строка получает элемент по текущему индексу i.
  • Integer nextElement = numbers.get(i + 1);: Эта строка получает элемент по следующему индексу i + 1.
  • System.out.println(...): Эти строки выводят информацию в консоль, показывая, какие элементы сравниваются и результат сравнения.
  • if, else if, else: Это условные операторы, которые проверяют, является ли currentElement меньше, больше или равен nextElement.

Сохраните файл ListComparison.java (Ctrl+S или Cmd+S).

Теперь скомпилируем и запустим программу. Откройте терминал внизу WebIDE. Убедитесь, что вы находитесь в директории ~/project (если нужно, вы можете использовать команду cd ~/project).

Скомпилируйте код с помощью javac:

javac ListComparison.java

Если ошибок нет, будет создан файл ListComparison.class. Теперь запустите скомпилированный код с помощью java:

java ListComparison

Вы должны увидеть вывод, похожий на следующий:

Original list: [1, 3, 2, 4, 5]
Comparing 1 and 3
1 is less than 3
Comparing 3 and 2
3 is greater than 2
Comparing 2 and 4
2 is less than 4
Comparing 4 and 5
4 is less than 5

Этот вывод показывает, что наша программа успешно перебрала элементы списка и сравнила каждую пару соседних элементов, выведя результат каждого сравнения.

Использование Stream API для проверки сортировки

На этом этапе мы рассмотрим более современный и часто более компактный способ проверки, отсортирован ли список, с использованием Stream API Java. Stream API, введенное в Java 8, предоставляет функциональный подход к обработке коллекций данных.

Мы модифицируем нашу предыдущую программу, добавив метод, который будет проверять, отсортирован ли список по возрастанию с использованием потоков (streams).

Откройте файл ListComparison.java в редакторе WebIDE. Добавьте новый метод с именем isSortedAscending в класс ListComparison, вне метода main, но внутри фигурных скобок {} класса ListComparison.

Вот обновленный код для ListComparison.java:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class ListComparison {

    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(3);
        numbers.add(2);
        numbers.add(4);
        numbers.add(5);

        System.out.println("Original list: " + numbers);

        // Check if the list is sorted using the new method
        boolean sorted = isSortedAscending(numbers);

        if (sorted) {
            System.out.println("The list is sorted in ascending order.");
        } else {
            System.out.println("The list is NOT sorted in ascending order.");
        }

        // The previous loop for comparison is removed for simplicity in this step
        // but you can keep it if you want to see both methods in action.
    }

    // Method to check if the list is sorted in ascending order using Streams
    public static boolean isSortedAscending(List<Integer> list) {
        if (list == null || list.size() <= 1) {
            return true; // An empty or single-element list is considered sorted
        }

        return IntStream.range(0, list.size() - 1)
                .allMatch(i -> list.get(i).compareTo(list.get(i + 1)) <= 0);
    }
}

Рассмотрим новые части кода:

  • import java.util.stream.IntStream;: Эта строка импортирует класс IntStream, который полезен для работы с последовательностями целых чисел в потоках.
  • public static boolean isSortedAscending(List<Integer> list): Эта строка объявляет новый статический метод с именем isSortedAscending, который принимает список (List) целых чисел (Integer) и возвращает логическое значение (boolean, true, если список отсортирован, и false в противном случае).
  • if (list == null || list.size() <= 1): Этот код обрабатывает крайние случаи: пустой список или список с одним элементом всегда считается отсортированным.
  • IntStream.range(0, list.size() - 1): Этот код создает поток целых чисел от 0 до (но не включая) list.size() - 1. Эти целые числа представляют индексы элементов списка, которые мы хотим сравнить.
  • .allMatch(i -> list.get(i).compareTo(list.get(i + 1)) <= 0): Это ядро операции с потоком.
    • allMatch() - это терминальная операция, которая проверяет, удовлетворяют ли все элементы потока заданному условию.
    • i -> list.get(i).compareTo(list.get(i + 1)) <= 0 - это лямбда-выражение, которое определяет условие. Для каждого индекса i из IntStream оно получает элемент по индексу i и элемент по индексу i + 1.
    • list.get(i).compareTo(list.get(i + 1)) сравнивает два элемента. Метод compareTo возвращает отрицательное целое число, если первый элемент меньше второго, ноль, если они равны, и положительное целое число, если первый элемент больше второго.
    • <= 0 проверяет, является ли результат compareTo меньше или равным нулю. Это условие истинно, если текущий элемент меньше или равен следующему элементу, что соответствует определению сортировки по возрастанию.
    • allMatch возвращает true только в том случае, если это условие истинно для всех соседних пар элементов в списке.

Сохраните файл ListComparison.java.

Теперь скомпилируйте и запустите обновленную программу в терминале:

javac ListComparison.java
java ListComparison

Теперь вывод должен показывать, отсортирован ли список по возрастанию на основе метода isSortedAscending:

Original list: [1, 3, 2, 4, 5]
The list is NOT sorted in ascending order.

Измените список в методе main так, чтобы он был отсортирован, например:

        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);

Сохраните файл, скомпилируйте и запустите программу снова. Теперь вывод должен быть следующим:

Original list: [1, 2, 3, 4, 5]
The list is sorted in ascending order.

Это демонстрирует, как использовать Stream API для выполнения компактной проверки сортировки по возрастанию.

Обработка различных порядков сортировки

На предыдущем этапе мы создали метод для проверки, отсортирован ли список по возрастанию. На этом этапе мы расширим нашу программу, чтобы она могла обрабатывать различные порядки сортировки: по возрастанию и по убыванию. Мы добавим новый метод, который будет принимать список и желаемый порядок сортировки в качестве входных параметров.

Откройте файл ListComparison.java в редакторе WebIDE. Мы добавим новый метод с именем isSorted, который принимает список и логическое значение (boolean), указывающее, хотим ли мы проверить сортировку по возрастанию (true) или по убыванию (false).

Вот обновленный код для ListComparison.java:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class ListComparison {

    public static void main(String[] args) {
        List<Integer> numbersAsc = new ArrayList<>();
        numbersAsc.add(1);
        numbersAsc.add(2);
        numbersAsc.add(3);
        numbersAsc.add(4);
        numbersAsc.add(5);

        List<Integer> numbersDesc = new ArrayList<>();
        numbersDesc.add(5);
        numbersDesc.add(4);
        numbersDesc.add(3);
        numbersDesc.add(2);
        numbersDesc.add(1);

        List<Integer> numbersUnsorted = new ArrayList<>();
        numbersUnsorted.add(1);
        numbersUnsorted.add(3);
        numbersUnsorted.add(2);
        numbersUnsorted.add(4);
        numbersUnsorted.add(5);


        System.out.println("Checking list: " + numbersAsc);
        System.out.println("Is ascending sorted? " + isSorted(numbersAsc, true));
        System.out.println("Is descending sorted? " + isSorted(numbersAsc, false));
        System.out.println();

        System.out.println("Checking list: " + numbersDesc);
        System.out.println("Is ascending sorted? " + isSorted(numbersDesc, true));
        System.out.println("Is descending sorted? " + isSorted(numbersDesc, false));
        System.out.println();

        System.out.println("Checking list: " + numbersUnsorted);
        System.out.println("Is ascending sorted? " + isSorted(numbersUnsorted, true));
        System.out.println("Is descending sorted? " + isSorted(numbersUnsorted, false));
        System.out.println();

    }

    // Method to check if the list is sorted based on the specified order
    public static boolean isSorted(List<Integer> list, boolean ascending) {
        if (list == null || list.size() <= 1) {
            return true; // An empty or single-element list is considered sorted
        }

        return IntStream.range(0, list.size() - 1)
                .allMatch(i -> {
                    int comparison = list.get(i).compareTo(list.get(i + 1));
                    if (ascending) {
                        return comparison <= 0; // For ascending, current must be <= next
                    } else {
                        return comparison >= 0; // For descending, current must be >= next
                    }
                });
    }
}

Рассмотрим изменения:

  • В методе main мы создали три разных списка: numbersAsc (отсортированный по возрастанию), numbersDesc (отсортированный по убыванию) и numbersUnsorted (неотсортированный).
  • Мы вызываем новый метод isSorted для каждого списка, передавая в качестве параметра ascending как true (для проверки сортировки по возрастанию), так и false (для проверки сортировки по убыванию).
  • public static boolean isSorted(List<Integer> list, boolean ascending): Это новая сигнатура метода, которая принимает список и логический флаг для указания порядка сортировки.
  • Внутри лямбда-выражения allMatch:
    • int comparison = list.get(i).compareTo(list.get(i + 1));: Мы выполняем сравнение соседних элементов.
    • if (ascending): Если флаг ascending равен true, мы проверяем, что comparison <= 0 (текущий элемент меньше или равен следующему).
    • else: Если флаг ascending равен false (то есть мы проверяем сортировку по убыванию), мы проверяем, что comparison >= 0 (текущий элемент больше или равен следующему).

Сохраните файл ListComparison.java.

Теперь скомпилируйте и запустите обновленную программу в терминале:

javac ListComparison.java
java ListComparison

Вывод должен показать результаты проверки каждого списка на сортировку как по возрастанию, так и по убыванию:

Checking list: [1, 2, 3, 4, 5]
Is ascending sorted? true
Is descending sorted? false

Checking list: [5, 4, 3, 2, 1]
Is ascending sorted? false
Is descending sorted? true

Checking list: [1, 3, 2, 4, 5]
Is ascending sorted? false
Is descending sorted? false

Это демонстрирует, как создать гибкий метод с использованием Stream API для проверки различных порядков сортировки, регулируя логику сравнения на основе входного параметра.

Резюме

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

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