How to write a Comparator as Lambda Expression

In this article, we will take a look at the different option to write a comparator as Lambda expression In Java. Java 8 provides a lot of features including the lambda expression and this article will use the same feature to write a comparator in Java.

Comparator as Lambda Expression

We use comparator when we want to sort a collection. Java provides option to use Comparable or Comparator interface to perform this sorting.This approach has a limitation as it can only compare the object with a certain type. Here is a standard code of using the comparator.

Comparator <ComparatorPerson> COMPARE_BY_NAME = new Comparator < ComparatorPerson > () {
    public int compare(ComparatorPerson one, ComparatorPerson other) {
        return one.name.compareTo(other.name);
    }
};

Java 8 lambda expression provide the option to write the above code is more readable and concise format. It also provide the option to use the multiple parameters for the comparison. Let’s see how to rewrite the above comparator as Lambda expression In Java.

Comparator <ComparatorPerson> byName = 
  (ComparatorPerson p1, ComparatorPerson p2) -> p1.getName().compareTo(p2.getName());

1. Example Overview

To understand, how to use a comparator as Lambda expression In Java and how to use the flexibility of the Java 8 lambda expression, I am using a Customer class. We will run our different use cases using this Customer Class.

package com.javadevjournal.data;

import lombok.Builder;
import lombok.Data;

import java.io.Serializable;

@Data
@Builder
public class Customer implements Serializable {

    private String firstName;
    private String lastName;
    private String email;
    private int age;
}

Using lombok for generating boilerplate code for our bean

private static List < Customer > getCustomers() {

    List <Customer> customers = new ArrayList();

    customers.add(Customer.builder().firstName("Robert").lastName("Hickle").age(62).email("[email protected]").build());
    customers.add(Customer.builder().firstName("Sandra").lastName("Hadleigh").age(21).email("[email protected]").build());
    customers.add(Customer.builder().firstName("Miller").lastName("Gerty").age(41).email("[email protected]").build());
    customers.add(Customer.builder().firstName("Milton").lastName("Arnison").age(30).email("[email protected]").build());
    customers.add(Customer.builder().firstName("Crissy").lastName("Finch").age(35).email("[email protected]").build());
    return customers;
}

Now we have the basic setup done, lets see the different option to write a comparator as Lambda expression In Java. We will start by sorting the input based on a given parameter.

2. Sort by Age

In our first example, we will sort the customer by age. I am taking age as an example, you can use firstName, lastName or any other parameter for the sorting based on your requirement.

public class CustomerService {

    public static void main(String[] args) {

        //sort customer by age
        List < Customer > customers = getCustomers();
        customers.sort(Comparator.comparing(Customer::getAge));
        //customers.forEach(System.out::println);

        //option 2
        List < Customer > customers1 = getCustomers();
        customers1.sort(Comparator.comparing(e - > e.getAge()));
        //customers1.forEach(System.out::println);

        //option 3 if we know the type
        customers.sort(Comparator.comparingInt(Customer::getAge));

        //pure lambda expression
        Collections.sort(customers, (c1, c2) - > c1.getAge() - c1.getAge()); //we careful when using this as it can cause overflow

    }

    private static List < Customer > getCustomers() {

        List < Customer > customers = new ArrayList();

        customers.add(Customer.builder()
            .firstName("Robert").lastName("Hickle")
            .age(62).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Sandra").lastName("Hadleigh")
            .age(21).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Miller").lastName("Gerty")
            .age(41).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Milton").lastName("Arnison")
            .age(30).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Crissy").lastName("Finch")
            .age(35).email("[email protected]").build());
            
        return customers;
    }
}

Output

Customer(firstName=Sandra, lastName=Hadleigh, [email protected], age=21)
Customer(firstName=Milton, lastName=Arnison, [email protected], age=30)
Customer(firstName=Crissy, lastName=Finch, [email protected], age=35)
Customer(firstName=Miller, lastName=Gerty, [email protected], age=41)
Customer(firstName=Robert, lastName=Hickle, [email protected], age=62)

Above example is a simple one where we are sorting the input based on a single parameter. There are certain cases where we may have to sort the data based on multiple inputs.Let’s say we want to sort customer first by their firstName and than use lastName as additional sort parameter.

3. Sort on Multiple Fields

This is a SQL like syntax which is really powerful to combine multiple attribute for the sorting. I am using firstName and lastName in the example but you can combine different attributes as per your requirement. Let’s see this in example.

public class CustomerService {

    public static void main(String[] args) {

        sortByFirstAndSecondName();
    }

    private static void sortByFirstAndSecondName() {
        List < Customer > customers = getCustomers();

        //Let's get the comparator
        Comparator < Customer > comparator = Comparator.comparing(Customer::getFirstName)
            .thenComparing(Customer::getLastName);

        customers.sort(comparator);

        //output
        customers.forEach(System.out::println);
    }

    private static List < Customer > getCustomers() {

        List < Customer > customers = new ArrayList();

        customers.add(Customer.builder()
            .firstName("Robert").lastName("Hickle")
            .age(62).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Sandra").lastName("Hadleigh")
            .age(21).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Miller").lastName("Gerty")
            .age(41).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Milton").lastName("Arnison")
            .age(30).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Crissy").lastName("Finch")
            .age(35).email("[email protected]")
            .build());

        return customers;
    }
}

Output

Customer(firstName=Crissy, lastName=Finch, [email protected], age=35)
Customer(firstName=Miller, lastName=Gerty, [email protected], age=41)
Customer(firstName=Milton, lastName=Arnison, [email protected], age=30)
Customer(firstName=Robert, lastName=Hickle, [email protected], age=62)
Customer(firstName=Sandra, lastName=Hadleigh, [email protected], age=21)

4. Sort in Reverse Order

How about if we want to sort but in reverse order? We have the option to write a comparator as Lambda expression to sort the input in reverse order. Let’s see how to do this:

package com.javadevjournal;

import com.javadevjournal.data.Customer;

import java.util.*;

public class CustomerService {

    public static void main(String[] args) {

        sortInReverseOrder();
    }

    private static void sortInReverseOrder() {
        List < Customer > customerList = getCustomers();
        Comparator < Customer > customerComparator = Comparator.comparing(e - > e.getAge());
        customerList.sort(customerComparator.reversed());
        customerList.forEach(System.out::println);
    }

    private static List < Customer > getCustomers() {

        List < Customer > customers = new ArrayList();

        customers.add(Customer.builder()
            .firstName("Robert").lastName("Hickle")
            .age(62).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Sandra").lastName("Hadleigh")
            .age(21).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Miller").lastName("Gerty")
            .age(41).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Milton").lastName("Arnison")
            .age(30).email("[email protected]")
            .build());

        customers.add(Customer.builder()
            .firstName("Crissy").lastName("Finch")
            .age(35).email("[email protected]")
            .build());

        return customers;
    }
}

Output

Customer(firstName=Robert, lastName=Hickle, [email protected], age=62)
Customer(firstName=Miller, lastName=Gerty, [email protected], age=41)
Customer(firstName=Crissy, lastName=Finch, [email protected], age=35)
Customer(firstName=Milton, lastName=Arnison, [email protected], age=30)
Customer(firstName=Sandra, lastName=Hadleigh, [email protected], age=21)

Summary

In this article, we saw the different option to write a comparator as Lambda expression In Java. Java 8 has brought a number of interesting and powerful feature and using the lambda expression to sort a given list is one of them. We saw how to use it to sort the list based on a given attribute or a set of attributes.

As always the source code for this article is available on our GitHub repository.