Construcción de Comparable usando utilidades personalizadas
En este ejemplo queremos ordenar instancias de la clase Person utilizando la interfaz Comparator. Para ello, vamos a implementar nuestros propia clase Utils para simplificar la creación de Comparators.
La clase Person tiene los atributos: name, surname, y age.
La clase Utils proporciona métodos genéricos para crear Comparators de una manera más sencilla. En lugar de definir cada Comparator manualmente, utilizamos el método comparing() de la clase Utils para generar comparadores basados en una función que extrae el atributo deseado de la instancia de Person.
import java.util.*;
import java.util.function.*;
class Person {
String name;
String surname;
int age;
public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName() {
return this.name;
}
public String getSurname() {
return this.surname;
}
public Integer getAge() {
return this.age;
}
}
class Utils {
public static > Comparator
comparing(Function
f) {
return (P p1, P p2) -> {
T ap1 = f.apply(p1);
T ap2 = f.apply(p2);
return ap1.compareTo(ap2);
};
}
}
public class Main {
public static void main(String[] args) {
Comparator<Person> byAge = Utils.comparing(Person::getAge);
Comparator<Person> bySurname = Utils.comparing(Person::getSurname);
Comparator<Person> byName = Utils.comparing(Person::getName);
Person p1 = new Person("Paco", "Lopez", 10);
Person p2 = new Person("Pepe", "Lopez", 10);
System.out.println(byAge.compare(p1, p2));
System.out.println(bySurname.compare(p1, p2));
System.out.println(byName.compare(p1, p2));
}
}
En el código anterior, hemos implementado comparadores utilizando comparing() que se encarga de la comparación según el atributo pasado como argumento. Ahora usaremos un nuevo método en la clase Utils llamado thenComparing().
El método thenComparing() permite encadenar comparaciones adicionales en caso de que la primera comparación devuelva un empate. Esto nos facilita la creación de comparadores más complejos, donde se compara primero un atributo y, si son iguales, se pasa a comparar otro atributo, y así sucesivamente.
class Utils {
public static > Comparator
comparing(Function
f) {
return (P p1, P p2) -> {
T ap1 = f.apply(p1);
T ap2 = f.apply(p2);
return ap1.compareTo(ap2);
};
}
public static
> Comparator
thenComparing(Comparator
c, Function
f) {
return (P p1, P p2) -> {
int alfa = c.compare(p1, p2);
if (alfa != 0) {
return alfa;
} else {
T ap1 = f.apply(p1);
T ap2 = f.apply(p2);
return ap1.compareTo(ap2);
}
};
}
}
public class Main {
public static void main(String[] args) {
Comparator<Person> byAge = Utils.comparing(Person::getAge);
Comparator<Person> byAgeAndSurname = Utils.thenComparing(byAge, Person::getSurname);
Comparator<Person> byAgeAndSurnameAndName = Utils.thenComparing(byAgeAndSurname, Person::getName);
Person p1 = new Person("Paco", "Lopez", 10);
Person p2 = new Person("Pepe", "Lopez", 10);
System.out.println(byAge.compare(p1, p2));
System.out.println(byAgeAndSurname.compare(p1, p2));
System.out.println(byAgeAndSurnameAndName.compare(p1, p2));
}
}