Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

230
Visualizações
What is the use of Comparator.comparing in respect to Comparator

As far as I understand Comparator is a functional interface used to compare 2 objects with int compare(T o1, T o2) as the abstract function that takes two argument. but there is also a function Comparator.comparing(s->s) that can take a lambda function with only one input parameter. for Example to sort a Collection using streams

        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));

the sorted method takes a Comparator as a argument. So I am able to understand the first lambda expression but I wonder the use of Comparator.comparing(s->s) i.e. is Comparator.comparing() used for converting a single argument lambda expression to a double argument one or does it has some other use as well. Also please explain the part of the below function declaration.

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

0

Comparator#compare(T o1, T o2) Compare two objects and returns an integer value based on this criteria:

  • A negative value if o1 < o2
  • A positive value if o1 > o2
  • Zero if they are equal.

Comparator.comparing(Function<? super T, ? extends U> key) returns a Comparator that compares by that sort key.

The main difference is that compare method provides a single point of comparison, whereas comparing chained to other functions to provide multiple points of comparison.

Suppose you have a class Person

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

if you compare two Person instances p1 vs p2 using compare(p1, p2), the comparison will be executed and the two objects will be sorted based on some natural ordering prescribed by the class. In contrast, if you want to compare the same two instances using comparing(), the comparison will be executed based on whichever criteria you choose to compare based on some attribute of the class. For example: Comparator.comparing(Person::getFirstName).

Because comparing returns a Comparator rather than a value, as I stated before, you can chain multiple comparisons. For instance: Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName);

As for the meaning of the return type <T, U extends Comparable<? super U>> Comparator<T>, you can find the explanation here.

I want to add that, classes must be comparable in order for compare(T o1, T o2) to work. String objects are comparable because they implement this interface. That said, if a class is not Comparable, you can still use comparing method because as I stated, you get to choose which attribute of the class you would like to use for the comparison and those attributes are likely to be comparable (i.e. String in the case of person's name or age in the above example).

over 4 years ago · Santiago Trujillo Relatório

0

is Comparator.comparing() used for converting a single argument lambda expression to a double argument?

Yes, you can sort of think of it like that.

When sorting things, you are supposed to specify "given two things a and b, which of them is greater, or are they equal?" using a Comparator<T>. The a and b is why it has 2 lambda parameters, and you return an integer indicating your answer to that question.

However, a much more convenient way to do this is to specify "given a thing x, what part of x do you want to sort by?". And that is what you can do with the keyExtractor argument of Comparator.comparing.

Compare:

/*
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

The latter is clearly much more concise and intuitive. We tend to think about what things to sort by, rather than how exactly to compare two things, and the exact number to return depending on the comparison result.

As for the declaration for comparing:

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

The <T, U extends Comparable<? super U>> part first declares two generic type parameters - T is what the comparator compares (Person in the above case), and U is the type that you are actually comparing (String in the above case), hence it extends Comparable.

keyExtractor is the parameter you pass in, such as x -> x.getName(), that should answer the question of "when given a T, what is a U that you want to compare by?".

If you are confused by the ? super and ? extends, read What is PECS?.

If you haven't realised already, the implementation of comparing basically boils down to:

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

0

Imagine you have your custom object:

public class Person {

  private String firstName;
  private String lastName;

  //getters and setters
}

Let's now say you have to compare people by their first names. One option is to write comparator like this:

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

This should be obvious - get first name of one person, and compare it to the first name of other person. Other option is to write this same comparator using Comparator.comparing(Function<? super T,? extends U> keyExtractor). It will look like this:

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

Or even better with method reference:

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

The single argument you provide here is a Function, it accepts a single parameter, this is why your lambda also uses a single parameter. The function here works as a key extractor - it extracts from your object the keys to be compared. It's like saying, get first name from first object and compare it to first name of second object.

Just note, that keys extracted like this must be Comparable. In the example above extracted key is String, which implements comparable.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda