- 按字母順序排序字符串列表
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
方法參數爲List
,Java 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/