Interfaz Comparator
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 45 de 87.
Mientras que Comparable define el orden natural de una clase, a veces es necesario ordenar objetos de diferentes maneras. La interfaz Comparator le permite crear una lógica de comparación independiente sin modificar la clase original.
Un Comparator es un objeto externo que compara dos objetos del mismo tipo. Esto es útil cuando deseas múltiples opciones de ordenación o cuando no puedes modificar la clase en sí misma:
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();
}
}Luego puedes pasar el comparador a los métodos de ordenación:
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
Collections.sort(people, new NameComparator()); // Ordenado por nombre
Collections.sort(people, new AgeComparator()); // Ordenado por edadPara escribir código conciso, puedes usar expresiones lambda ya que Comparator es una interfaz funcional:
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));La diferencia clave: Comparable es implementada por la clase que se está comparando y define un orden natural, mientras que Comparator es una clase separada que puede definir ordenamientos personalizados ilimitados.
Desafío
FácilVamos a construir un sistema de ordenación de empleados que demuestre el poder de la interfaz Comparator. Crearás múltiples comparadores para ordenar empleados de diferentes maneras—por salario y por nombre—sin modificar la clase Employee en sí misma.
Organizarás tu código en cuatro archivos:
Employee.java: Crea una clase que represente a un empleado con tres campos privados:name(String),department(String) ysalary(double). Incluye un constructor para inicializar todos los campos y métodos getter para cada uno. SobrescribetoString()para que devuelva:[name] ([department]) - $[salary]SalaryComparator.java: Crea un comparador que ordene a los empleados por salario en orden descendente (el mejor pagado primero). Implementa la interfazComparator<Employee>y su métodocompare(). UsaDouble.compare()para una comparación segura de los valores de salario.NameComparator.java: Crea otro comparador que ordene a los empleados alfabéticamente por nombre en orden ascendente (de la A a la Z). ImplementaComparator<Employee>y usa el métodocompareTo()de String para la comparación.Main.java: Une todo creando una lista de empleados y ordenándolos usando tus comparadores. Recibirás la entrada de tres empleados, cada uno en una línea separada con el formato:name,department,salaryCrea un
ArrayListde empleados, luego demuestra ambos enfoques de ordenación:- Primero, ordena por salario usando tu
SalaryComparatore imprime cada empleado - Imprime una línea vacía
- Luego ordena por nombre usando tu
NameComparatore imprime cada empleado
- Primero, ordena por salario usando tu
Recibirás tres líneas de entrada, cada una con los datos del empleado en el formato: name,department,salary
Por ejemplo, una línea de entrada podría verse así: Alice,Engineering,75000.0
Recuerda importar java.util.Comparator en tus archivos de comparadores, y java.util.ArrayList, java.util.Collections y java.util.Scanner en tu archivo Main. ¡Observa cómo los comparadores te permiten definir múltiples estrategias de ordenación externamente—la clase Employee no necesita saber nada sobre cómo podría ser ordenada!
Hoja de referencia
La interfaz Comparator le permite crear una lógica de comparación externa para ordenar objetos sin modificar la clase original. Esto es útil cuando necesita múltiples opciones de ordenación.
Un Comparator compara dos objetos del mismo tipo implementando el 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());
}
}Pase el comparador a los métodos de ordenación:
Collections.sort(people, new NameComparator());Puede utilizar expresiones lambda para obtener un código conciso, ya que Comparator es una interfaz funcional:
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));Para comparar valores numéricos, utilice métodos de clases envolventes como Double.compare() para una comparación segura:
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}Diferencia clave: Comparable define un orden natural dentro de la propia clase, mientras que Comparator es una clase separada que puede definir ordenaciones personalizadas ilimitadas de forma externa.
Pruébalo tú mismo
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);
// Leer tres empleados de la entrada
// Formato de cada línea: name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: Analizar cada línea y crear objetos Employee
// Hint: Usar split(",") para separar los valores
// TODO: Crear un ArrayList de empleados y añadir los tres
// TODO: Ordenar por salary usando SalaryComparator e imprimir cada empleado
// Hint: Usar Collections.sort(list, comparator)
// TODO: Imprimir una línea vacía
// TODO: Ordenar por name usando NameComparator e imprimir cada empleado
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator