Use Comparator.comparing to make the comparators. Just figure out what you want to compare. It will looks something like this, except you will write whatever logic you want to use to extract the values to compare:

Comparator<Parent> byAttr1ofFirstChild = Comparator.comparing(
    parent -> parent.getChildren().get(0).getAttr1()
);

Comparator<Parent> byAttr1ofFirstGrandChild = Comparator.comparing(
    parent -> parent.getChildren().get(0).getGrandChildren().get(0).getAttr1()
);


List<Parent> sortedList = parents.stream()
    .sorted(byAttr1ofFirstChild.thenComparing(byAttr1ofFirstGrandChild))
    .collect(toList());

Comparator.comparing would also make the examples in your question much nicer (using static imports) :

Comparator<Parent> byFirst = comparing(Parent::getAttrib1, reverseOrder());
Comparator<Parent> bySecond = comparing(Parent::getAttrib2);
Answer from Misha on Stack Overflow
🌐
SWTestAcademy
swtestacademy.com › home › java streams comparators with examples
Java Streams Comparators with Examples
October 10, 2021 - We will learn Java Streams Comparators like Comparator.comparing(), sorted(Comparator.naturalOrder()), sorted(Comparator.reverseOrder().
🌐
Baeldung
baeldung.com › home › java › guide to java comparator.comparing()
Guide to Java Comparator.comparing() | Baeldung
January 8, 2024 - In this tutorial, we’ll explore several functions introduced for the Comparator interface in Java 8. For the examples in this tutorial, let’s create an Employee bean and use its fields for comparing and sorting purposes:
🌐
GeeksforGeeks
geeksforgeeks.org › java › stream-sorted-comparator-comparator-method-java
Stream sorted (Comparator comparator) method in Java - GeeksforGeeks
December 26, 2025 - Example 1: This code demonstrates how to sort a stream of strings in reverse (descending) order using Stream.sorted(Comparator.reverseOrder()). ... import java.util.*; class GFG { public static void main(String[] args) { List<String> list = ...
Top answer
1 of 4
14

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));
2 of 4
7

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<T> 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<Person> {
    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).

🌐
Baeldung
baeldung.com › home › java › java – powerful comparison with lambdas
Java – Powerful Comparison with Lambdas | Baeldung
January 8, 2024 - In this tutorial, we’re going to take a first look at the Lambda support in Java 8, specifically how to leverage it to write the Comparator and sort a Collection. This article is part of the “Java – Back to Basic” series here on Baeldung. The article is an example-heavy introduction of the possibilities and operations offered by the Java 8 Stream API.
🌐
Readthedocs
java-8-tips.readthedocs.io › en › stable › comparator.html
7. Comparator — Java 8 tips 1.0 documentation
To compare two elements of type ... words based on word lengths Function<String, Integer> keyExtractor = str -> str.length(); Stream.of("grapes", "milk", "pineapple", "water-melon") .sorted(Comparator.comparing(keyExtractor)) .forEach(System.out::println);...
🌐
Medium
medium.com › @coffeeandtips.tech › using-comparator-comparing-to-sort-java-stream-a6e0302dce1a
Using Comparator.comparing to sort Java Stream | by Coffee and Tips | Medium
December 2, 2023 - In this post, we are going to show that using Comparator.comparing to sort Java Stream can make sorting elegant and efficient.
Find elsewhere
🌐
Tabnine
tabnine.com › home page › code › java › java.util.comparator
java.util.Comparator.comparing java code examples | Tabnine
@VisibleForTesting static void sortByInsertionTime(List<RemoteTaskRunnerWorkItem> tasks) { Collections.sort(tasks, Comparator.comparing(RemoteTaskRunnerWorkItem::getQueueInsertionTime)); } ... public void forEach( BiConsumer<String,URI> consumer ) { entries.stream().collect( Collectors.groupingBy( e -> e.key ) ) .forEach( ( key, list ) -> list.stream() .max( Comparator.comparing( e -> e.precedence ) ) .ifPresent( e -> consumer.accept( key, e.uri ) ) ); }
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › Comparator.html
Comparator (Java Platform SE 8 )
October 20, 2025 - The returned comparator is serializable if the specified comparator is also serializable. ... For example, to sort a collection of String based on the length and then case-insensitive natural ordering, the comparator can be composed using following code,
🌐
TutorialsPoint
tutorialspoint.com › java-program-to-sort-string-stream-with-reversed-comparator
Java program to sort string stream with reversed comparator
... import java.util.Arrays; import ... "Thor"); System.out.println("Initial List = "+list); System.out.println("Reverse..."); Comparator<String> comp = (aName, bName) -> aName.compareTo(bName); list.stream().sorted(comp.reversed()) .forEach(System.out::println); } ...
🌐
Baeldung
baeldung.com › home › java › core java › comparator and comparable in java
Comparator and Comparable in Java | Baeldung
March 26, 2025 - We can build one simply by making use of the Comparator or Comparable interfaces. Let’s use an example of a football team, where we want to line up the players by their rankings.
🌐
Blogger
javarevisited.blogspot.com › 2021 › 09 › comparator-comparing-thenComparing-example-java-.html
Java 8 Comparator comparing() and thenComparing() Example - Tutorial
Overall these new Comparator methods make comparing objects really easy and fun as you can also pass both lambda expression and method reference to this method, making it super easy to write custom Comparators on the fly as shown in the following example but before that let's create a custom Java object or POJO (Plain Old Java object to demonstrate this comparison and sorting example in Java.
🌐
Javabrahman
javabrahman.com › java-8 › the-complete-java-8-comparator-tutorial-with-examples
The Complete Java 8 Comparator Tutorial with examples
Java 8's Comparator as an assignment target for LambdaExpressions Given the fact that its a functional interface, an instance of a Comparator can now be created in Java 8 with a lambda expression specifying its comparison logic. Take a look at the code snippet below - ... package com.javabrahman.java8.comparator; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import com.javabrahman.java8.Employee; public class ComparatorsInJava8 { static List<Employee> employeeList = Arrays.asList(new Employee("Tom Jones", 45), new Employee("Harry Maj
🌐
Java Guides
javaguides.net › 2020 › 04 › java-8-stream-sorting-with-comparator.html
Java 8 Stream - Sorting with Comparator Example
September 23, 2024 - This example demonstrates different ways to sort List of String objects in descending order using Java 8 Stream APIs: import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class StreamListSorting { public static void main(String[] args) { List < String > fruits = new ArrayList < String > (); fruits.add("Banana"); fruits.add("Apple"); fruits.add("Mango"); fruits.add("Orange"); // descending order List < String > sortedList3 = fruits.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); System.out.println(sortedList3); List < String > sortedList4 = fruits.stream().sorted((o1, o2) -> o2.compareTo(o1)).collect(Collectors.toList()); System.out.println(sortedList4); } }
🌐
Medium
medium.com › @AlexanderObregon › javas-stream-sorted-method-explained-52b9b25e9f84
Java’s Stream.sorted() Method Explained | Medium
December 26, 2024 - Combining comparators is particularly useful in applications where data must be grouped hierarchically, such as organizing inventory or categorizing products in an online store. Filtering and Sorting Together Combining Stream.sorted() with filtering operations can refine datasets before sorting them. For instance, filtering and sorting a list of products based on price thresholds: import java.util.Arrays; import java.util.List; public class FilterAndSortExample { static class Product { String name; double price; Product(String name, double price) { this.name = name; this.price = price; } @Over
🌐
Medium
hudsonmendes.medium.com › comparator-vs-compartor-comparing-when-sorting-java-streams-8a98da021668
Comparator<> vs Compartor.comparing when sorting Java Streams
August 4, 2023 - Comparator vs Compartor.comparing when sorting Java Streams Reduce the amount of comparators you have using Comparator.comparing(). When implementing sorting logic, it’s common to choose one out …
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › sorting a stream by multiple fields in java
Sorting a Stream by Multiple Fields in Java - Group by sort example
March 10, 2022 - //first name comparator Comparator<Employee> compareByFirstName = Comparator.comparing( Employee::getFirstName ); //last name comparator Comparator<Employee> compareByLastName = Comparator.comparing( Employee::getLastName ); //Compare by first ...
🌐
Coderanch
coderanch.com › t › 753856 › java › sort-stream-java-lang-reflect
How do I sort a stream if I only have java.lang.reflect.Field? (Features new in Java 8 forum at Coderanch)
The only thing I have in my code is Field from java.lang.reflect package. Is there any way I can actually sort my collection based on that field? Let's say I have class Apple with properties color and weight. And in my code, I write: ... Collections.sort(List) requires the generic type T to be Compareable. Otherwise you have to provide a Comparator<T> to use with Collections.sort(List, Comparator). Sorting streams work similar: Either the type is Compareable itself or you have to provide a Comparator.