Como Verificar se uma Lista Está Ordenada em Java

JavaBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá como verificar se uma lista está ordenada em Java. Exploraremos diferentes abordagens para realizar essa tarefa, começando com um método fundamental de comparação de elementos adjacentes dentro da lista.

Em seguida, você descobrirá como aproveitar o poder da Java Stream API para uma maneira mais concisa e potencialmente eficiente de realizar a verificação de ordenação. Finalmente, abordaremos como lidar com diferentes ordens de classificação, como ascendente e descendente, para tornar suas verificações de ordenação mais versáteis.

Comparar Elementos Adjacentes da Lista

Nesta etapa, aprenderemos como comparar elementos adjacentes em uma lista (ou, mais especificamente, uma List em Java). Esta é uma tarefa comum quando você precisa verificar padrões ou ordem dentro de uma sequência de dados. Começaremos criando um programa Java simples que usa um loop para iterar por uma lista e comparar cada elemento com o que vem logo após ele.

Primeiro, vamos criar um novo arquivo Java chamado ListComparison.java no seu diretório ~/project. Você pode fazer isso usando o File Explorer do WebIDE à esquerda. Clique com o botão direito na área ~/project, selecione "New File" e digite ListComparison.java.

Agora, abra o arquivo ListComparison.java no editor e adicione o seguinte código:

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);
            }
        }
    }
}

Vamos detalhar este código:

  • import java.util.ArrayList; e import java.util.List;: Estas linhas importam as classes necessárias para trabalhar com listas em Java.
  • List<Integer> numbers = new ArrayList<>();: Isso cria uma nova lista chamada numbers que pode conter objetos Integer (números inteiros).
  • numbers.add(...): Estas linhas adicionam elementos à nossa lista.
  • for (int i = 0; i < numbers.size() - 1; i++): Este é um loop for que itera pela lista. Observe que a condição do loop é i < numbers.size() - 1. Isso é importante porque estamos comparando numbers.get(i) com numbers.get(i + 1). Se fizéssemos um loop até numbers.size(), i + 1 sairia dos limites na última iteração.
  • Integer currentElement = numbers.get(i);: Isso obtém o elemento no índice atual i.
  • Integer nextElement = numbers.get(i + 1);: Isso obtém o elemento no próximo índice i + 1.
  • System.out.println(...): Estas linhas imprimem informações no console, mostrando quais elementos estão sendo comparados e o resultado da comparação.
  • if, else if, else: Estas são instruções condicionais que verificam se o currentElement é menor que, maior que ou igual ao nextElement.

Salve o arquivo ListComparison.java (Ctrl+S ou Cmd+S).

Agora, vamos compilar e executar o programa. Abra o Terminal na parte inferior do WebIDE. Certifique-se de estar no diretório ~/project (você pode usar cd ~/project se necessário).

Compile o código usando javac:

javac ListComparison.java

Se não houver erros, um arquivo ListComparison.class será criado. Agora, execute o código compilado usando java:

java ListComparison

Você deve ver uma saída semelhante a esta:

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

Esta saída mostra que nosso programa iterou com sucesso pela lista e comparou cada par adjacente de elementos, imprimindo o resultado de cada comparação.

Usar a Stream API para Verificação de Ordenação

Nesta etapa, exploraremos uma maneira mais moderna e, muitas vezes, mais concisa de verificar se uma lista está ordenada usando a Java Stream API. A Stream API, introduzida no Java 8, fornece uma abordagem funcional para processar coleções de dados.

Modificaremos nosso programa anterior para incluir um método que verifica se a lista está ordenada em ordem crescente usando streams.

Abra o arquivo ListComparison.java no editor do WebIDE. Adicione um novo método chamado isSortedAscending à classe ListComparison, fora do método main, mas dentro das chaves {} da classe ListComparison.

Aqui está o código atualizado para 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);
    }
}

Vamos analisar as novas partes:

  • import java.util.stream.IntStream;: Isso importa a classe IntStream, que é útil para trabalhar com sequências de inteiros em streams.
  • public static boolean isSortedAscending(List<Integer> list): Isso declara um novo método estático chamado isSortedAscending que recebe uma List de Integer e retorna um boolean (true se estiver ordenado, false caso contrário).
  • if (list == null || list.size() <= 1): Isso lida com casos extremos: uma lista vazia ou uma lista com um elemento é sempre considerada ordenada.
  • IntStream.range(0, list.size() - 1): Isso cria um stream de inteiros de 0 até (mas não incluindo) list.size() - 1. Esses inteiros representam os índices dos elementos da lista que queremos comparar.
  • .allMatch(i -> list.get(i).compareTo(list.get(i + 1)) <= 0): Esta é a parte central da operação de stream.
    • allMatch() é uma operação terminal que verifica se todos os elementos no stream correspondem a uma determinada condição.
    • i -> list.get(i).compareTo(list.get(i + 1)) <= 0 é uma expressão lambda que define a condição. Para cada índice i do IntStream, ele obtém o elemento no índice i e o elemento no índice i + 1.
    • list.get(i).compareTo(list.get(i + 1)) compara os dois elementos. compareTo retorna um inteiro negativo se o primeiro elemento for menor que o segundo, zero se forem iguais e um inteiro positivo se o primeiro elemento for maior que o segundo.
    • <= 0 verifica se o resultado de compareTo é menor ou igual a zero. Essa condição é verdadeira se o elemento atual for menor ou igual ao próximo elemento, que é a definição de ordem crescente.
    • allMatch retorna true somente se essa condição for verdadeira para todos os pares adjacentes na lista.

Salve o arquivo ListComparison.java.

Agora, compile e execute o programa atualizado no Terminal:

javac ListComparison.java
java ListComparison

A saída agora deve indicar se a lista está ordenada em ordem crescente com base no método isSortedAscending:

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

Modifique a lista no método main para que ela esteja ordenada, por exemplo:

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

Salve o arquivo, compile e execute novamente. A saída agora deve ser:

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

Isso demonstra como usar a Stream API para realizar uma verificação concisa de ordem crescente.

Lidar com Diferentes Ordens de Ordenação

Na etapa anterior, criamos um método para verificar se uma lista está ordenada em ordem crescente. Nesta etapa, expandiremos nosso programa para lidar com diferentes ordens de ordenação: crescente e decrescente. Adicionaremos um novo método que recebe a lista e a ordem de ordenação desejada como entrada.

Abra o arquivo ListComparison.java no editor do WebIDE. Adicionaremos um novo método chamado isSorted que recebe a lista e um boolean indicando se queremos verificar a ordem crescente (true) ou decrescente (false).

Aqui está o código atualizado para 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
                    }
                });
    }
}

Vamos analisar as mudanças:

  • Criamos três listas diferentes em main: numbersAsc (ordenada crescentemente), numbersDesc (ordenada decrescentemente) e numbersUnsorted.
  • Chamamos o novo método isSorted com cada lista e ambos true (para crescente) e false (para decrescente) para o parâmetro ascending.
  • public static boolean isSorted(List<Integer> list, boolean ascending): Esta é nossa nova assinatura de método, aceitando a lista e um sinalizador booleano para a ordem.
  • Dentro da lambda allMatch:
    • int comparison = list.get(i).compareTo(list.get(i + 1));: Realizamos a comparação entre elementos adjacentes.
    • if (ascending): Se o sinalizador ascending for verdadeiro, verificamos se comparison <= 0 (o atual é menor ou igual ao próximo).
    • else: Se o sinalizador ascending for falso (significando que estamos verificando a ordem decrescente), verificamos se comparison >= 0 (o atual é maior ou igual ao próximo).

Salve o arquivo ListComparison.java.

Agora, compile e execute o programa atualizado no Terminal:

javac ListComparison.java
java ListComparison

A saída deve mostrar os resultados da verificação de cada lista em relação às ordens crescente e decrescente:

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

Isso demonstra como criar um método flexível usando a Stream API para verificar diferentes ordens de ordenação, ajustando a lógica de comparação com base em um parâmetro de entrada.

Resumo

Neste laboratório, aprendemos como verificar se uma lista está ordenada em Java usando diferentes abordagens. Começamos implementando um método para comparar elementos adjacentes em uma lista usando um loop tradicional, o que fornece uma compreensão fundamental da lógica de verificação de ordenação. Isso envolveu iterar pela lista e comparar cada elemento com seu sucessor para identificar quaisquer pares não ordenados.

Posteriormente, exploramos como aproveitar a Java Stream API para uma abordagem mais concisa e funcional para verificar a ordenação de listas. Este método utiliza operações de stream para determinar eficientemente se os elementos estão na ordem desejada. Finalmente, abordamos o tratamento de diferentes ordens de ordenação (crescente e decrescente) ao realizar a verificação de ordenação, demonstrando como adaptar a lógica de comparação para acomodar vários requisitos de ordenação.