Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

233
Vistas
¿Cuál es el uso de Comparator.comparing con respecto a Comparator?

Según tengo entendido, Comparator es una interfaz funcional que se usa para comparar 2 objetos con int compare(T o1, T o2) como la función abstracta que toma dos argumentos. pero también hay una función Comparator.comparing(s->s) que puede tomar una función lambda con solo un parámetro de entrada. por ejemplo, para ordenar una colección usando flujos

 List<String> projects=Arrays.asList("abc","def","sss","aaa","bbb"); projects.stream().sorted((x,y)->y.compareTo(x)).forEach(s->System.out.println(s)); projects.stream().sorted(Comparator.comparing(s->s)).forEach(s->System.out.println(s));

el método sorted toma un Comparator como argumento. Así que puedo entender la primera expresión lambda, pero me pregunto el uso de Comparator.comparing(s->s) es decir, Comparator.comparing() se usa para convertir una expresión lambda de un solo argumento en una de doble argumento o tiene algún otro uso también. También explique la parte de la siguiente declaración de función.

 public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor)
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Comparator#compare(T o1, T o2) Compara dos objetos y devuelve un valor entero basado en este criterio:

  • Un valor negativo si o1 < o2
  • Un valor positivo si o1 > o2
  • Cero si son iguales.

Comparator.comparing(Function<? super T, ? extends U> key) devuelve un Comparator que compara según esa clave de ordenación.

La principal diferencia es que el método de compare proporciona un único punto de comparación, mientras que la comparing está encadenada a otras funciones para proporcionar múltiples puntos de comparación.

Supongamos que tiene una Person de clase

 public class Person implements Comparable { private String firstName; private String lastName; private int age; // rest of class omitted }

si compara dos instancias de Person p1 vs p2 usando compare(p1, p2) , la comparación se ejecutará y los dos objetos se ordenarán según algún orden natural prescrito por la clase. Por el contrario, si desea comparar las mismas dos instancias mediante comparing() , la comparación se ejecutará en función de los criterios que elija para comparar en función de algún atributo de la clase. Por ejemplo: Comparator.comparing(Person::getFirstName) .

Debido a que la comparing devuelve un Comparator en lugar de un valor, como dije antes, puede encadenar múltiples comparaciones. Por ejemplo: Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName);

En cuanto al significado del tipo de retorno <T, U extends Comparable<? super U>> Comparator<T> , puede encontrar la explicación aquí .

Quiero agregar que las clases deben ser comparables para que compare(T o1, T o2) funcione. Los objetos de cadena son comparables porque implementan esta interfaz. Dicho esto, si una clase no es Comparable , aún puede usar el método de comparing porque, como dije, puede elegir qué atributo de la clase le gustaría usar para la comparación y es probable que esos atributos sean comparables (es decir, Cadena en el caso del nombre o la edad de la persona en el ejemplo anterior).

over 4 years ago · Santiago Trujillo Denunciar

0

¿Se usa Comparator.comparing() para convertir una expresión lambda de un solo argumento en un argumento doble?

Sí, puedes pensarlo así.

Al clasificar las cosas, se supone que debe especificar "dados dos elementos a y b , ¿cuál de ellos es mayor o son iguales?" usando un Comparator<T> . El a y b es por qué tiene 2 parámetros lambda, y devuelve un número entero que indica su respuesta a esa pregunta.

Sin embargo, una forma mucho más conveniente de hacer esto es especificar "dada una cosa x , ¿ por qué parte de x desea ordenar?". Y eso es lo que puede hacer con el argumento keyExtractor de Comparator.comparing .

Comparar:

 /* given two people, a and b, the comparison result between a and b is the comparison result between a's name and b's name */ Comparator<Person> personNameComparator = (a, b) -> a.getName().compareTo(b.getName()); /* given a person x, compare their name */ Comparator<Person> personNameComparator = Comparator.comparing(x -> x.getName()); // or Person::getName

Este último es claramente mucho más conciso e intuitivo. Tendemos a pensar en qué cosas clasificar, en lugar de cómo comparar exactamente dos cosas, y el número exacto que devolverá según el resultado de la comparación.

En cuanto a la declaración para comparing :

 public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor)

La <T, U extends Comparable<? super U>> la parte <T, U extends Comparable<? super U>> primero declara dos parámetros de tipo genérico: T es lo que compara el comparador ( Person en el caso anterior), y U es el tipo que realmente está comparando ( String en el caso anterior), por lo tanto, extends Comparable .

keyExtractor es el parámetro que pasa, como x -> x.getName() , que debería responder a la pregunta de "cuando se le da una T , ¿qué es una U con la que desea comparar?".

Si está confundido por el ? super y ? extends , lea ¿Qué es PECS? .

Si aún no se ha dado cuenta, la implementación de la comparing básicamente se reduce a:

 return (a, b) -> keyExtractor.apply(a).compareTo(keyExtractor.apply(b));
over 4 years ago · Santiago Trujillo Denunciar

0

Imagina que tienes tu objeto personalizado:

 public class Person { private String firstName; private String lastName; //getters and setters }

Digamos ahora que tienes que comparar a las personas por sus nombres de pila. Una opción es escribir comparador como este:

 Comparator<Person> comparator2 = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());

Esto debería ser obvio: obtener el nombre de pila de una persona y compararlo con el nombre de pila de otra persona. Otra opción es escribir este mismo comparador usando Comparator.comparing(Function<? super T,? extends U> keyExtractor) . Se verá así:

 Comparator<Person> comparator1 = Comparator.comparing(p -> p.getFirstName());

O incluso mejor con la referencia del método:

 Comparator<Person> comparator1 = Comparator.comparing(Person::getFirstName);

El único argumento que proporciona aquí es una función , acepta un solo parámetro, es por eso que su lambda también usa un solo parámetro. La función aquí funciona como un extractor de claves: extrae de su objeto las claves que se compararán. Es como decir, obtener el nombre del primer objeto y compararlo con el nombre del segundo objeto.

Solo tenga en cuenta que las claves extraídas de esta manera deben ser Comparable . En el ejemplo anterior, la clave extraída es String , que implementa comparable.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda