Comparator e Comparable

JavaBeginner
Pratique Agora

Introdução

Em aplicações Java, frequentemente precisamos comparar e ordenar objetos. Para tipos de dados primitivos como inteiros ou strings, o Java já sabe como compará-los. No entanto, para objetos personalizados, precisamos dizer ao Java como eles devem ser comparados e ordenados.

O Java fornece duas interfaces para auxiliar com isso:

  • A interface Comparable permite que uma classe defina sua ordenação natural.
  • A interface Comparator fornece lógica de comparação externa que pode ser usada para diferentes critérios de ordenação.

Neste laboratório, você aprenderá como implementar ambas as interfaces e usá-las para ordenar coleções de objetos de várias maneiras.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível intermediário com uma taxa de conclusão de 55%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Entendendo a Interface Comparable

A interface Comparable é usada quando uma classe possui uma ordenação natural. Por exemplo, strings são naturalmente ordenadas alfabeticamente, e inteiros são naturalmente ordenados numericamente.

Quando uma classe implementa a interface Comparable, ela deve definir um método compareTo() que especifica como as instâncias da classe devem ser ordenadas.

Criando uma Classe Student Básica

Vamos criar uma classe Student simples para demonstrar como usar a interface Comparable. Definiremos um aluno com nome, GPA (Grade Point Average - Média de Notas) e número de matrícula.

  1. Abra o WebIDE e crie um novo arquivo chamado Student.java no diretório ~/project com o seguinte código:
public class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;

    public Student(String name, double gpa, int regNo) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
    }

    // Implementing the compareTo method from Comparable interface
    @Override
    public int compareTo(Student other) {
        // Compare students based on GPA
        if (this.gpa < other.gpa) {
            return -1;
        } else if (this.gpa > other.gpa) {
            return 1;
        } else {
            return 0;
        }
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    @Override
    public String toString() {
        return name + ", GPA: " + gpa + ", Reg No: " + regNo;
    }
}

Vamos entender este código:

  • A classe Student implementa a interface Comparable<Student>
  • O método compareTo() compara os alunos com base em seu GPA
  • Se o GPA do aluno atual for menor que o GPA do outro aluno, retornamos -1
  • Se o GPA do aluno atual for maior que o GPA do outro aluno, retornamos 1
  • Se os GPAs forem iguais, retornamos 0

Agora, vamos criar um programa de teste simples para ver como podemos usar a interface Comparable para ordenar alunos.

  1. Crie um novo arquivo chamado ComparableDemo.java no diretório ~/project com o seguinte código:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparableDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort the list using the natural ordering (defined by compareTo method)
        Collections.sort(students);

        // Print the sorted list
        System.out.println("\nStudents sorted by GPA (using Comparable):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa:

  1. Cria uma lista de objetos Student

  2. Imprime a lista não ordenada

  3. Ordena a lista usando Collections.sort(), que usa a ordenação natural definida pelo método compareTo()

  4. Imprime a lista ordenada

  5. Agora, vamos compilar e executar nosso código para ver a saída:

cd ~/project
javac Student.java ComparableDemo.java
java ComparableDemo

Você deve ver uma saída semelhante a:

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by GPA (using Comparable):
Alice, GPA: 3.2, Reg No: 103
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Bob, GPA: 3.9, Reg No: 104

Como você pode ver, os alunos agora estão ordenados por seu GPA em ordem crescente. Esta é a ordenação natural que definimos no método compareTo().

Criando e Usando Comparators

Enquanto a interface Comparable define uma ordenação natural para uma classe, às vezes precisamos ordenar objetos com base em critérios diferentes. É aqui que a interface Comparator entra em ação.

A interface Comparator nos permite definir lógica de ordenação personalizada que é separada da classe que está sendo comparada. Isso significa que podemos ter várias maneiras de ordenar a mesma classe de objetos.

Criando um Comparator para Ordenação Baseada em Nome

Vamos criar um Comparator que ordene os alunos por seus nomes alfabeticamente:

  1. Crie um novo arquivo chamado StudentNameComparator.java no diretório ~/project com o seguinte código:
import java.util.Comparator;

public class StudentNameComparator implements Comparator<Student> {
    @Override
    public int compare(Student s1, Student s2) {
        // Compare students based on their names
        return s1.getName().compareTo(s2.getName());
    }
}

Este Comparator:

  • Implementa a interface Comparator<Student>
  • Define um método compare() que recebe dois objetos Student
  • Compara os alunos com base em seus nomes usando o próprio método compareTo() da classe String
  1. Agora, vamos criar um programa para demonstrar como usar este Comparator. Crie um arquivo chamado ComparatorDemo.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using the StudentNameComparator
        Collections.sort(students, new StudentNameComparator());

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using Comparator):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa:

  1. Cria uma lista de objetos Student

  2. Imprime a lista não ordenada

  3. Ordena a lista usando Collections.sort() com nosso StudentNameComparator personalizado

  4. Imprime a lista ordenada

  5. Vamos compilar e executar nosso código:

cd ~/project
javac Student.java StudentNameComparator.java ComparatorDemo.java
java ComparatorDemo

Você deve ver uma saída semelhante a:

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by name (using Comparator):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

Como você pode ver, os alunos agora estão ordenados alfabeticamente por nome, em vez de por GPA.

Usando Expressões Lambda para Comparadores

O Java 8 introduziu expressões lambda, que podem simplificar a criação de comparadores. Em vez de criar uma classe separada, podemos definir a lógica de comparação embutida.

  1. Crie um novo arquivo chamado LambdaComparatorDemo.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class LambdaComparatorDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Sort by registration number using lambda expression
        Collections.sort(students, (s1, s2) -> s1.getRegNo() - s2.getRegNo());

        // Print the list sorted by registration number
        System.out.println("Students sorted by registration number (using lambda):");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using method reference
        Collections.sort(students, Comparator.comparing(Student::getName));

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using method reference):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa demonstra:

  1. Usando uma expressão lambda para criar um comparador que ordena os alunos por número de matrícula

  2. Usando o método Comparator.comparing() com uma referência de método para criar um comparador que ordena os alunos por nome

  3. Compile e execute este código:

cd ~/project
javac Student.java LambdaComparatorDemo.java
java LambdaComparatorDemo

Você deve ver uma saída semelhante a:

Students sorted by registration number (using lambda):
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by name (using method reference):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

Os alunos são primeiro ordenados por número de matrícula e, em seguida, por nome.

Técnicas Avançadas de Ordenação

Em aplicações do mundo real, muitas vezes precisamos de uma lógica de ordenação mais complexa, como:

  • Ordenar por múltiplos critérios (por exemplo, ordenar por GPA e, se os GPAs forem iguais, ordenar por nome)
  • Ordenar em ordem inversa
  • Criar cadeias de comparadores personalizados

Vamos explorar essas técnicas avançadas.

Ordenando por Múltiplos Critérios

  1. Crie um novo arquivo chamado MultiCriteriaDemo.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MultiCriteriaDemo {
    public static void main(String[] args) {
        // Create a list of students with some having the same GPA
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
        students.add(new Student("Bob", 3.8, 104));   // Same GPA as Mary
        students.add(new Student("Charlie", 3.2, 105));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort first by GPA, then by name
        Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
        Comparator<Student> byName = Comparator.comparing(Student::getName);

        // Combine the comparators using thenComparing
        Comparator<Student> byGpaThenName = byGpa.thenComparing(byName);

        // Sort the list
        Collections.sort(students, byGpaThenName);

        // Print the sorted list
        System.out.println("\nStudents sorted by GPA, then by name:");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa:

  1. Cria uma lista de alunos, com alguns tendo o mesmo GPA

  2. Cria um comparador para GPA e um comparador para nome

  3. Combina esses comparadores usando o método thenComparing()

  4. Ordena os alunos primeiro por GPA e, em seguida, por nome se os GPAs forem iguais

  5. Compile e execute o código:

cd ~/project
javac Student.java MultiCriteriaDemo.java
java MultiCriteriaDemo

Você deve ver uma saída semelhante a:

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105

Students sorted by GPA, then by name:
Charlie, GPA: 3.2, Reg No: 105
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102

Observe que os alunos com o mesmo GPA (Alice e John com 3.5, Bob e Mary com 3.8) são ordenados alfabeticamente.

Ordenando em Ordem Inversa

  1. Crie um novo arquivo chamado ReverseOrderDemo.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ReverseOrderDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));
        students.add(new Student("Charlie", 3.0, 105));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Method 1: Using Collections.reverseOrder() with a comparator
        Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
        Comparator<Student> byGpaReversed = Collections.reverseOrder(byGpa);

        Collections.sort(students, byGpaReversed);

        System.out.println("\nStudents sorted by GPA in descending order (Method 1):");
        for (Student student : students) {
            System.out.println(student);
        }

        // Method 2: Using the reversed() method of Comparator
        Collections.sort(students, Comparator.comparing(Student::getName).reversed());

        System.out.println("\nStudents sorted by name in reverse alphabetical order (Method 2):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa demonstra duas maneiras de ordenar em ordem inversa:

  1. Usando Collections.reverseOrder() para inverter um comparador

  2. Usando o método reversed() de um comparador

  3. Compile e execute o código:

cd ~/project
javac Student.java ReverseOrderDemo.java
java ReverseOrderDemo

Você deve ver uma saída semelhante a:

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
Charlie, GPA: 3.0, Reg No: 105

Students sorted by GPA in descending order (Method 1):
Bob, GPA: 3.9, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Alice, GPA: 3.2, Reg No: 103
Charlie, GPA: 3.0, Reg No: 105

Students sorted by name in reverse alphabetical order (Method 2):
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.0, Reg No: 105
Bob, GPA: 3.9, Reg No: 104
Alice, GPA: 3.2, Reg No: 103

A primeira ordenação mostra os alunos em ordem decrescente por GPA, e a segunda ordenação mostra os alunos em ordem alfabética inversa por nome.

Cadeia de Ordenação Complexa

  1. Vamos criar mais um exemplo que combina múltiplos critérios e ordenação inversa. Crie um arquivo chamado ComplexSortingDemo.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComplexSortingDemo {
    public static void main(String[] args) {
        // Create a list of students with varied data
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
        students.add(new Student("Bob", 3.8, 104));   // Same GPA as Mary
        students.add(new Student("Charlie", 3.2, 105));
        students.add(new Student("David", 3.2, 106)); // Same GPA as Charlie

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Create a complex sorting chain:
        // 1. Sort by GPA in descending order
        // 2. If GPAs are equal, sort by name in ascending order
        // 3. If names are also equal, sort by registration number in descending order
        Comparator<Student> complexComparator = Comparator
            .comparing(Student::getGpa, Comparator.reverseOrder())
            .thenComparing(Student::getName)
            .thenComparing(Student::getRegNo, Comparator.reverseOrder());

        Collections.sort(students, complexComparator);

        System.out.println("\nStudents sorted by complex criteria:");
        System.out.println("(GPA descending, then name ascending, then reg. number descending)");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Este programa cria uma cadeia de ordenação complexa que:

  1. Primeiro ordena os alunos por GPA em ordem decrescente

  2. Se os GPAs forem iguais, ordena por nome em ordem crescente

  3. Se tanto o GPA quanto o nome forem iguais, ordena por número de matrícula em ordem decrescente

  4. Compile e execute o código:

cd ~/project
javac Student.java ComplexSortingDemo.java
java ComplexSortingDemo

Você deve ver uma saída semelhante a:

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106

Students sorted by complex criteria:
(GPA descending, then name ascending, then reg. number descending)
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106

Nesta saída:

  • Bob e Mary têm um GPA de 3.8, mas Bob vem primeiro alfabeticamente
  • Alice e John têm um GPA de 3.5, mas Alice vem primeiro alfabeticamente
  • Charlie e David têm um GPA de 3.2, e Charlie vem primeiro alfabeticamente

Isso demonstra como você pode criar uma lógica de ordenação complexa e multinível, encadeando comparadores.

Construindo uma Aplicação Completa de Ordenação

Agora que aprendemos sobre a interface Comparable, a interface Comparator e várias técnicas de ordenação, vamos juntar tudo em uma aplicação completa.

Criaremos um sistema de gerenciamento de alunos que permite ordenar os alunos de diferentes maneiras.

  1. Primeiro, vamos criar uma versão atualizada da nossa classe Student. Esta versão implementará Comparable e incluirá um método toString() aprimorado para melhor exibição. Crie um arquivo chamado StudentManager.java no diretório ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;
    private String major;

    public Student(String name, double gpa, int regNo, String major) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
        this.major = major;
    }

    @Override
    public int compareTo(Student other) {
        // Default natural ordering by registration number
        return this.regNo - other.regNo;
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    public String getMajor() {
        return major;
    }

    @Override
    public String toString() {
        return String.format("%-10s | GPA: %.1f | Reg No: %-5d | Major: %-10s",
                            name, gpa, regNo, major);
    }
}

public class StudentManager {
    private List<Student> students;

    public StudentManager() {
        students = new ArrayList<>();
        // Add some sample students
        students.add(new Student("John", 3.5, 101, "Computer Science"));
        students.add(new Student("Mary", 3.8, 102, "Physics"));
        students.add(new Student("Alice", 3.5, 103, "Mathematics"));
        students.add(new Student("Bob", 3.9, 104, "Computer Science"));
        students.add(new Student("Charlie", 3.2, 105, "Physics"));
        students.add(new Student("David", 3.6, 106, "Mathematics"));
        students.add(new Student("Eve", 3.8, 107, "Biology"));
    }

    public void displayStudents() {
        System.out.println("----------------------------------------------------------");
        System.out.println("Name       | GPA   | Reg No | Major      ");
        System.out.println("----------------------------------------------------------");
        for (Student student : students) {
            System.out.println(student);
        }
        System.out.println("----------------------------------------------------------");
    }

    public void sortByNaturalOrder() {
        Collections.sort(students);
        System.out.println("\nStudents sorted by registration number (natural order):");
        displayStudents();
    }

    public void sortByName() {
        Collections.sort(students, Comparator.comparing(Student::getName));
        System.out.println("\nStudents sorted by name:");
        displayStudents();
    }

    public void sortByGpaDescending() {
        Collections.sort(students, Comparator.comparing(Student::getGpa).reversed());
        System.out.println("\nStudents sorted by GPA (descending):");
        displayStudents();
    }

    public void sortByMajorThenGpa() {
        Collections.sort(students,
            Comparator.comparing(Student::getMajor)
                     .thenComparing(Student::getGpa, Comparator.reverseOrder()));
        System.out.println("\nStudents sorted by major, then by GPA (descending):");
        displayStudents();
    }

    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("\nStudent Manager");
            System.out.println("1. Display students (unsorted)");
            System.out.println("2. Sort by registration number");
            System.out.println("3. Sort by name");
            System.out.println("4. Sort by GPA (highest first)");
            System.out.println("5. Sort by major, then by GPA (highest first)");
            System.out.println("6. Exit");
            System.out.print("Enter your choice: ");

            int choice = scanner.nextInt();

            switch (choice) {
                case 1:
                    System.out.println("\nUnsorted student list:");
                    manager.displayStudents();
                    break;
                case 2:
                    manager.sortByNaturalOrder();
                    break;
                case 3:
                    manager.sortByName();
                    break;
                case 4:
                    manager.sortByGpaDescending();
                    break;
                case 5:
                    manager.sortByMajorThenGpa();
                    break;
                case 6:
                    System.out.println("Exiting program. Goodbye!");
                    scanner.close();
                    return;
                default:
                    System.out.println("Invalid choice. Please try again.");
            }
        }
    }
}

Esta aplicação:

  1. Define uma classe Student com nome, GPA, número de matrícula e curso

  2. Implementa Comparable para definir a ordenação natural por número de matrícula

  3. Cria uma classe StudentManager que mantém uma lista de alunos

  4. Fornece métodos para ordenar os alunos de diferentes maneiras

  5. Inclui uma interface simples baseada em menu para o usuário escolher diferentes opções de ordenação

  6. Compile e execute a aplicação:

cd ~/project
javac StudentManager.java
java StudentManager
  1. Teste a aplicação tentando várias opções de ordenação. Aqui está uma interação de exemplo:
Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 1

Unsorted student list:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 3

Students sorted by name:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 5

Students sorted by major, then by GPA (descending):
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 6
Exiting program. Goodbye!

Você pode experimentar diferentes opções de ordenação para ver como a lista de alunos é exibida de forma diferente a cada vez.

Esta aplicação completa demonstra o poder e a flexibilidade das interfaces Comparable e Comparator em Java. Ela permite que você ordene objetos de várias maneiras para atender aos diferentes requisitos de sua aplicação.

Resumo

Neste laboratório, você aprendeu como comparar e ordenar objetos em Java usando as interfaces Comparable e Comparator.

Conceitos-chave abordados:

  1. Interface Comparable

    • Implementando o método compareTo() para definir a ordenação natural de uma classe
    • Usando Collections.sort() com objetos naturalmente ordenados
  2. Interface Comparator

    • Criando comparadores personalizados para diferentes critérios de ordenação
    • Usando Collections.sort() com um comparador personalizado
    • Usando expressões lambda e referências de método para criação concisa de comparadores
  3. Técnicas Avançadas de Ordenação

    • Ordenando por múltiplos critérios usando thenComparing()
    • Ordenando em ordem inversa usando Collections.reverseOrder() ou reversed()
    • Criando cadeias de ordenação complexas
  4. Aplicação Prática

    • Construindo um sistema completo de gerenciamento de alunos com várias opções de ordenação
    • Implementando uma interface de usuário para demonstrar diferentes capacidades de ordenação

Essas capacidades de ordenação são fundamentais para muitas aplicações Java, especialmente aquelas que lidam com coleções de dados. Seja ordenando alunos em um sistema de gerenciamento de alunos, pedidos em uma aplicação de e-commerce ou qualquer outro tipo de dado, as técnicas que você aprendeu neste laboratório o ajudarão a implementar uma lógica de ordenação eficiente e flexível.