List 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 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 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 & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
List 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 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() {
@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 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() {
@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 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/