Sunday, June 28, 2015

Java 8: Composing Comparators

In my last post, I showed how you can sort a list of Person objects by age, using the following statement:

list.sort(comparingInt(Person::getAge));

What if you want to sort the objects in order of decreasing age instead? There's no need to create a new instance of Comparator, because the Comparator interface has a handy default method reversed that reverses its ordering:

list.sort(comparingInt(Person::getAge).reversed());

Now, what if you want to sort people by name if they have the same age. The thenComparing method allows you to do just that, as shown below:

list.sort(comparingInt(Person::getAge)
    .reversed()
    .thenComparing(Person::getName));

Saturday, June 27, 2015

Java 8: Sorting a List using Lambdas and Method References

This post shows how you can use Java 8 lambda expressions and method references to sort a list of Person objects by age. In Java 8, the List interface has a sort method, which expects a Comparator to compare two objects.

Traditionally, you would either sort a list by creating a specific class that implements the Comparator interface, like this:

public class AgeComparator implements Comparator<Person> {
  @Override
  public int compare(Person p1, Person p2) {
    return Integer.compare(p1.getAge(), p2.getAge());
  }
}

list.sort(new AgeComparator());

or, you would use an anonymous class, like this:

list.sort(new Comparator<Person>() {
  @Override
  public int compare(Person p1, Person p2) {
    return Integer.compare(p1.getAge(), p2.getAge());
  }
});

As you can see, this is quite verbose!

Java 8 introduces lambda expressions, which allow you to pass code more concisely. Since Comparator is a functional interface, you can use a lambda expression to sort the list:

list.sort((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()));

You may have noticed that the Comparator class has a static method called comparingInt that takes a ToIntFunction and returns a Comparator object. So, we can rewrite the code above to:

import static java.util.Comparator.comparingInt;
list.sort(comparingInt(p -> p.getAge()));

Finally, we can improve our code even further by using a method reference, which is just "syntactic sugar" for a lambda expression:

list.sort(comparingInt(Person::getAge));

The final solution is not only shorter but is also easier to read :)