Java 8 中的List排序

  • 按字母順序排序字符串列表
List<String> cities = Arrays.asList(
       "Milan",
       "london",
       "San Francisco",
       "Tokyo",
       "New Delhi"
);
System.out.println(cities);
//[Milan, london, San Francisco, Tokyo, New Delhi]

cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
//[london, Milan, New Delhi, San Francisco, Tokyo]

cities.sort(Comparator.naturalOrder());
System.out.println(cities);
//[Milan, New Delhi, San Francisco, Tokyo, london]

Java 7中,我們使用Collections.sort對List進行排序,Collections.sort方法參數爲ListJava 8中新增了一個集合方法List.sort,方法接受參數Comparator

  • 排序整數集合
List<Integer> numbers = Arrays.asList(6, 2, 1, 4, 9);
System.out.println(numbers); //[6, 2, 1, 4, 9]

numbers.sort(Comparator.naturalOrder());
System.out.println(numbers); //[1, 2, 4, 6, 9]
  • 按某個字符串屬性列排序
List<Movie> movies = Arrays.asList(
        new Movie("Lord of the rings"),
        new Movie("Back to the future"),
        new Movie("Carlito's way"),
        new Movie("Pulp fiction"));

movies.sort(Comparator.comparing(Movie::getTitle));

movies.forEach(System.out::println);

結果輸出

Movie{title='Back to the future'}
Movie{title='Carlito's way'}
Movie{title='Lord of the rings'}
Movie{title='Pulp fiction'}

我們注意到,給sort方法傳遞的並非Comparator類型,但結果仍然正確排序,原因就在於我們比較的屬性列是String,而String已經實現了Comparable接口,查看Comparator.comparing()的定義實現,我們可以看到其其調用的就是比較關鍵字的compareTo方法

return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
  • 按Double類型排序
List<Movie> movies = Arrays.asList(
        new Movie("Lord of the rings", 8.8),
        new Movie("Back to the future", 8.5),
        new Movie("Carlito's way", 7.9),
        new Movie("Pulp fiction", 8.9));

movies.sort(Comparator.comparingDouble(Movie::getRating)
                      .reversed());

movies.forEach(System.out::println);

本質上,Comparator.comparingDouble()調用的還是Double.compare()的方法,同樣類似的還有comparingInt()comparingLong()方法

  • 自定義比較規則

比如,對於我們之前提到的Movie,這裏我們需要按星標排序,那麼我們可以自定義Comparator實現類

List<Movie> movies = Arrays.asList(
        new Movie("Lord of the rings", 8.8, true),
        new Movie("Back to the future", 8.5, false),
        new Movie("Carlito's way", 7.9, true),
        new Movie("Pulp fiction", 8.9, false));

movies.sort(new Comparator<Movie>() {
    @Override
    public int compare(Movie m1, Movie m2) {
        if(m1.getStarred() == m2.getStarred()){
            return 0;
        }
        return m1.getStarred() ? -1 : 1;
     }
});

movies.forEach(System.out::println);

得到輸出結果如下:

List<Movie> movies = Arrays.asList(
        new Movie("Lord of the rings", 8.8, true),
        new Movie("Back to the future", 8.5, false),
        new Movie("Carlito's way", 7.9, true),
        new Movie("Pulp fiction", 8.9, false));

movies.sort(new Comparator<Movie>() {
    @Override
    public int compare(Movie m1, Movie m2) {
        if(m1.getStarred() == m2.getStarred()){
            return 0;
        }
        return m1.getStarred() ? -1 : 1;
     }
});

movies.forEach(System.out::println);

當然,我們也可以Lambda表達式以匿名類簡寫如下:

movies.sort((m1, m2) -> {
    if(m1.getStarred() == m2.getStarred()){
        return 0;
    }
    return m1.getStarred() ? -1 : 1;
});

或者通過Comparator.comparing()方法

movies.sort(Comparator.comparing(Movie::getStarred, (star1, star2) -> {
    if(star1 == star2){
         return 0;
    }
    return star1 ? -1 : 1;
}));
  • chain of Comparator排序集合

還是上面的例子,如果我們需要首先按電影星標,然後再按評分高低排序,那麼我們可以通過如下方式實現。

List<Movie> movies = Arrays.asList(
        new Movie("Lord of the rings", 8.8, true),
        new Movie("Back to the future", 8.5, false),
        new Movie("Carlito's way", 7.9, true),
        new Movie("Pulp fiction", 8.9, false));

movies.sort(Comparator.comparing(Movie::getStarred)
                      .reversed()
                      .thenComparing(Comparator.comparing(Movie::getRating)
                      .reversed())
);

movies.forEach(System.out::println);

我們可以得到排序結果如下:

Movie{starred=true, title='Lord of the rings', rating=8.8}
Movie{starred=true, title='Carlito's way', rating=7.9}
Movie{starred=false, title='Pulp fiction', rating=8.9}
Movie{starred=false, title='Back to the future', rating=8.5}

原文鏈接:

https://reversecoding.net/java-8-comparator-how-to-sort-a-list/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章