使用 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));