1, an overview of the

In this tutorial, we’ll take a look at Lambda expressions in the upcoming JDK 8 — specifically, how to use them to write comparators and sort collections.

This article is part of the “Java — Back to Basic” series on Baeldung.

First, let’s define a simple entity class:

public class Human {
    private String name;
    private int age;

    public Human() {
        super();
    }

    public Human(final String name, final int age) {
        super();

        this.name = name;
        this.age = age;
    }

    // standard getters and setters
}
Copy the code

2. Do not use basic ordering of Lambda expressions

Before Java 8, sorting a collection created an anonymous inner class for the Comparator to sort:

new Comparator<Human>() {
    @Override
    public int compare(Human h1, Human h2) {
        returnh1.getName().compareTo(h2.getName()); }}Copy the code

Simply use it to sort the list of Human entities:

@Test
public void givenPreLambda_whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
    Collections.sort(humans, new Comparator<Human>() {
        @Override
        public int compare(Human h1, Human h2) {
            returnh1.getName().compareTo(h2.getName()); }}); Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
Copy the code

3. Use basic ordering of Lambda expressions

According to the introduction of Lambda expressions, we can now get the same result using simple, practical semantics without using anonymous inner classes.

(final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName());
Copy the code

Similarly, we can now test its behavior as before:

@Test
public void whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));

    humans.sort((Human h1, Human h2) -> h1.getName().compareTo(h2.getName()));
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
Copy the code

Note: We also use the new sort API, which was added to java.util.List in Java 8 — not the old collections.sort API.

There is no basic sorting of Type Definitions

We further simplify the expression by not specifying a type definition — the compiler can make its own type judgments:

(h1, h2) -> h1.getName().compareTo(h2.getName())
Copy the code

The tests are still very similar:

@Test
public void givenLambdaShortForm_whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));

    humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
Copy the code

5. Sort using references to static methods

Next we’ll use Lambda expressions with static method references to sort.

First, we define the compareByNameThenAge method, which has the exact same signature as the compareTo method in the Comparator object:

public static int compareByNameThenAge(Human lhs, Human rhs) {
    if (lhs.name.equals(rhs.name)) {
        return lhs.age - rhs.age;
    } else {
        returnlhs.name.compareTo(rhs.name); }}Copy the code

Now, we’ll use this reference to call the humans.sort method:

humans.sort(Human::compareByNameThenAge);
Copy the code

The end result is a valid sorting collection that uses static methods as comparators:

@Test
public void givenMethodDefinition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));

    humans.sort(Human::compareByNameThenAge);
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
Copy the code

6. Extract the Comparator for sorting

We can avoid defining comparison logic by using a reference to the instance method and the Comparator.comparing method, which extracts and creates a Comparable based on that function.

We’re going to use the getName() getter method to build the Lambda expression and sort the list by name:

@Test
public void givenInstanceMethod_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));

    Collections.sort(humans, Comparator.comparing(Human::getName));
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
Copy the code

7. Reverse sort

JDK 8 also provides a useful way to reverse the Comparator (reverse Comparator) — we can quickly reverse our sorting:

@Test
public void whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), new Human("Jack", 12));
    Comparator<Human> comparator = (h1, h2) -> h1.getName().compareTo(h2.getName());

    humans.sort(comparator.reversed());
    Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}
Copy the code

8. Multi-conditional sorting

Lambda expressions for comparison operations are not always this simple — we could also write more complex expressions, such as sorting entities by name and then by age:

@Test
public void whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12));

    humans.sort((lhs, rhs) -> {
        if (lhs.getName().equals(rhs.getName())) {
            return lhs.getAge() - rhs.getAge();
        } else {
            returnlhs.getName().compareTo(rhs.getName()); }}); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}
Copy the code

9. Multi-condition combination sorting

The same comparison logic — sorting first by name and then by age — can be implemented using Comparator’s new combinatorial support.

Starting with JDK 8, we can now chain multiple comparators together to build more complex comparison logic:

@Test
public void givenComposition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12));

    humans.sort(Comparator.comparing(Human::getName).thenComparing(Human::getAge));
    Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}
Copy the code

10 and summarize

This article illustrates a variety of exciting ways to sort lists using Java 8 Lambda expressions — the correct use of past syntactic sugar and real, useful semantics.

The implementations and code snippets for all of these examples are available on my Github project — it’s an Eclipse-based project, so it should be easy to import and run.


Welcome to Zhihu columnKeeping up with Java8, share excellent Java8 Chinese guides and tutorials, and welcome to contribute high-quality articles.

Original link:
baeldung


Translation:
ImportNew.com –
Into the forest


Translation link:
www.importnew.com/15259.html