使用 Lambda 表达式对集合进行排序

排序列表

在 Java 8 之前,有必要在排序列表 1 时使用匿名(或命名)类实现 java.util.Comparator 接口 :

Version => Java SE 1.2
List<Person> people = ...
Collections.sort(
    people,
    new Comparator<Person>() {
        public int compare(Person p1, Person p2){
            return p1.getFirstName().compareTo(p2.getFirstName());
        }
    }
);

从 Java 8 开始,匿名类可以用 lambda 表达式替换。请注意,参数 p1p2 的类型可以省略,因为编译器会自动推断它们:

Collections.sort(
    people, 
    (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName())
);

通过使用 Comparator.comparing 和使用::(双冒号)符号表示的方法引用, 可以简化该示例。

Collections.sort(
    people,
    Comparator.comparing(Person::getFirstName)
);

静态导入允许我们更简洁地表达这一点,但这是否会提高整体可读性是值得商榷的:

import static java.util.Collections.sort;
import static java.util.Comparator.comparing;
//...
sort(people, comparing(Person::getFirstName));

以这种方式构建的比较器也可以链接在一起。例如,在使用他们的名字比较人之后,如果有人使用相同的名字,thenComparing 方法也会按姓氏进行比较:

sort(people, comparing(Person::getFirstName).thenComparing(Person::getLastName));

1 - 请注意,Collections.sort(...) 仅适用于 List 的子类型的集合。SetCollection API 并不意味着元素的任何排序。

排序地图

你可以按类似的方式按值分类 HashMap 的条目。 (注意,必须使用 LinkedHashMap 作为目标。普通 HashMap 中的键是无序的。)

Map<String, Integer> map = new HashMap();  // ... or any other Map class
// populate the map
map = map.entrySet()
    .stream()
    .sorted(Map.Entry.<String, Integer>comparingByValue())
    .collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue(),
                              (k, v) -> k, LinkedHashMap::new));