Java 8 Lambda 和 Comparator 排序

这里将演示 Java 8 中,几种使用 Ladmbda 结合 Comparator 进行 List 排序(升序或降序)的方式。

下面的示例中会用到 Person 类,Person 类的定义如下:

public class Person {
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    // toString...
    // get...set...
}

1. Comparator 排序

Comparator 是 Java 8 之前常用的排序方式,下面是排序 Person 类中的 age 字段的示例。

public static void main(String[] args) {
    List<Person> list = new ArrayList<>();
    list.add(new Person("Chris", 20));
    list.add(new Person("Linda", 10));
    list.add(new Person("Jack", 30));
    Collections.sort(list, new Comparator<Person>() {
    		@Override
    		public int compare(Person o1, Person o2) {
    		    return o1.getAge() - o2.getAge();
    		}
		});
    for (Person person : list) {
        System.out.println(person);
    }
}

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}

这里是一个匿名内部类方式的实现,为了一行排序代码写的代码是不是有点多了?

2. Lambda 和 Comparator 排序

public static void main(String[] args) {
    List<Person> list = new ArrayList<>();
    list.add(new Person("Chris", 20));
    list.add(new Person("Linda", 10));
    list.add(new Person("Jack", 30));
    sort(list);
    list.forEach(System.out::println);
}

private static List<Person> sort(List<Person> list) {
    Comparator<Person> byAge = (Person o1, Person o2) -> o1.getAge().compareTo(o2.getAge());
    list.sort(byAge);
    return list;
}

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}

也可以使用 Lambda 结合函数接口来完成 Comparator 的定义操作。

private static List<Person> sort(List<Person> list) {
    Comparator<Person> byAge = Comparator.comparing(Person::getAge);
    list.sort(byAge);
    return list;
}

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}

当然也可以进一步简化代码,像下面这样。

list.sort(Comparator.comparing(Person::getAge));

当需要排其他字段排序,如 name 字段,可以直接改为。

list.sort(Comparator.comparing(Person::getName));

输出:

Person{name='Chris', age=20}
Person{name='Jack', age=30}
Person{name='Linda', age=10}

3. 排序反转

下面的示例演示按 age 字段降序和升序的排序方式。

List<Person> list = new ArrayList<>();
list.add(new Person("Chris", 20));
list.add(new Person("Linda", 10));
list.add(new Person("Jack", 30));

list.sort((p1, p2) -> p1.getAge() - p2.getAge());
list.forEach(System.out::println);
System.out.println("--------");

list.sort((p1, p2) -> p2.getAge() - p1.getAge());
list.forEach(System.out::println);

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}
--------
Person{name='Jack', age=30}
Person{name='Chris', age=20}
Person{name='Linda', age=10}

也可以用另外的一种方式:

Comparator<Person> comparing = Comparator.comparing(Person::getAge);
list.sort(comparing);
list.forEach(System.out::println);

System.out.println("--------");

list.sort(comparing.reversed());
list.forEach(System.out::println);

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}
--------
Person{name='Jack', age=30}
Person{name='Chris', age=20}
Person{name='Linda', age=10}

4. Lambda 和 Comparator 和 Stream 排序

有时需要使用 stream 的 API,顺便排序可以使用 streamsorted 方法。

List<com.wdbyte.comparator.Person> list = new ArrayList<>();
list.add(new com.wdbyte.comparator.Person("Chris", 20));
list.add(new com.wdbyte.comparator.Person("Linda", 10));
list.add(new com.wdbyte.comparator.Person("Jack", 30));

list.stream()
    .sorted(Comparator.comparing(Person::getAge))
    .forEach(System.out::println);
System.out.println("----------");
list.stream()
    .sorted(Comparator.comparing(Person::getAge).reversed())
    .forEach(System.out::println);

输出:

Person{name='Linda', age=10}
Person{name='Chris', age=20}
Person{name='Jack', age=30}
----------
Person{name='Jack', age=30}
Person{name='Chris', age=20}
Person{name='Linda', age=10}

文中的代码存放在:github.com/niumoo/JavaNotes