Interface Comparator
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 45 de 87.
Enquanto o Comparable define a ordenação natural de uma classe, às vezes você precisa ordenar objetos de maneiras diferentes. A interface Comparator permite que você crie uma lógica de comparação separada sem modificar a classe original.
Um Comparator é um objeto externo que compara dois objetos do mesmo tipo. Isso é útil quando você deseja múltiplas opções de ordenação ou quando não pode modificar a própria classe:
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}Você pode então passar o comparador para métodos de ordenação:
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
Collections.sort(people, new NameComparator()); // Ordenado por nome
Collections.sort(people, new AgeComparator()); // Ordenado por idadePara um código conciso, você pode usar expressões lambda, já que Comparator é uma interface funcional:
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));A principal diferença: Comparable é implementado pela classe que está sendo comparada e define uma ordem natural, enquanto Comparator é uma classe separada que pode definir ordenações personalizadas ilimitadas.
Desafio
FácilVamos construir um sistema de ordenação de funcionários que demonstra o poder da interface Comparator. Você criará múltiplos comparadores para ordenar funcionários de diferentes maneiras—por salário e por nome—sem modificar a classe Employee em si.
Você organizará seu código em quatro arquivos:
Employee.java: Crie uma classe representando um funcionário com três campos privados:name(String),department(String) esalary(double). Inclua um construtor para inicializar todos os campos e métodos getter para cada um. SobrescrevatoString()para retornar:[name] ([department]) - $[salary]SalaryComparator.java: Crie um comparador que ordena funcionários por salário em ordem decrescente (maior salário primeiro). Implemente a interfaceComparator<Employee>e seu métodocompare(). UseDouble.compare()para uma comparação segura de valores de salário.NameComparator.java: Crie outro comparador que ordena funcionários alfabeticamente por nome em ordem crescente (A a Z). ImplementeComparator<Employee>e use o métodocompareTo()da String para a comparação.Main.java: Reúna tudo criando uma lista de funcionários e ordenando-os usando seus comparadores. Você receberá a entrada para três funcionários, cada um em uma linha separada no formato:name,department,salaryCrie um
ArrayListde funcionários e, em seguida, demonstre ambas as abordagens de ordenação:- Primeiro, ordene por salário usando seu
SalaryComparatore imprima cada funcionário - Imprima uma linha vazia
- Depois, ordene por nome usando seu
NameComparatore imprima cada funcionário
- Primeiro, ordene por salário usando seu
Você receberá três linhas de entrada, cada uma contendo dados de funcionários no formato: name,department,salary
Por exemplo, uma linha de entrada pode ser: Alice,Engineering,75000.0
Lembre-se de importar java.util.Comparator em seus arquivos de comparador, e java.util.ArrayList, java.util.Collections e java.util.Scanner em seu arquivo Main. Observe como os comparadores permitem definir múltiplas estratégias de ordenação externamente—a classe Employee não precisa saber nada sobre como ela pode ser ordenada!
Folha de consulta
A interface Comparator permite que você crie uma lógica de comparação externa para ordenar objetos sem modificar a classe original. Isso é útil quando você precisa de múltiplas opções de ordenação.
Um Comparator compara dois objetos do mesmo tipo ao implementar o método compare():
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}Passe o comparador para os métodos de ordenação:
Collections.sort(people, new NameComparator());Você pode usar expressões lambda para um código conciso, já que Comparator é uma interface funcional:
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));Para comparar valores numéricos, use métodos de classes wrapper como Double.compare() para uma comparação segura:
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}Diferença principal: Comparable define uma ordem natural dentro da própria classe, enquanto Comparator é uma classe separada que pode definir ordenações personalizadas ilimitadas externamente.
Experimente você mesmo
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lê três funcionários da entrada
// Formato de cada linha: name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: Analisar cada linha e criar objetos Employee
// Dica: Use split(",") para separar os valores
// TODO: Criar um ArrayList de funcionários e adicionar os três
// TODO: Ordenar por salário usando SalaryComparator e imprimir cada funcionário
// Dica: Use Collections.sort(list, comparator)
// TODO: Imprimir uma linha vazia
// TODO: Ordenar por nome usando NameComparator e imprimir cada funcionário
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator