How to sort Objects by a Field based on a Custom Comparator in Java

So, you have some instances of a class and you want to sort them based on a specific field, but without using the natural order of such a field. That is, you rather need to provide a specific comparator for such a field.

public class Person {

    private Address address;

    private LocalDate birthday;

    //getters and setters
}

public class Address {

    private String city;

    private String state;

    private String street;

    //getters and setters
}

Let's first clarify how we could sort instances of Person based on the natural order of one of its fields, e.g. the birthday.

persons.stream().sort(Comparator.comparing(Person::getBirthday));

Cool. Now, let's consider how to order Person based on their Address. Better, let's imagine to have to sort them based on the city and street without considering the state.

We then need a customised comparator to order Address. We can achieve this by chaining the Comparator above:

Comparator<Address> byCityAndStreet =
    Comparator.comparing(Address::getCity).thenComparing(Address::getStreet);

This first compares Address based on the city field, then if this is not decisive (i.e. two addresses with the same city) compares them based on their street.

Perfect, the next step is to use this comparator to sort the Person. This is possible thanks to another method of the Comparator interface: comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator). In this method, keyExtractor specify how to extract the key used in the comparison, then applies keyComparator to it!

persons.stream().sort(Comparator.comparing(Person::getAddress), byCityAndStreet);

And here we are, we have successfully sorted java objects based on a custom comparator applied to two fields of a nested object.