写业务时常常免不了对一组数据进行排序,比如 将用户按年龄大小排序、将学生按成绩高低排序等。更复杂的排序可能会涉及多个条件,比如 商品按价格大小排序且价格相同时按销量高低排序。
在 jdk8 之前,我们基本上是通过实现 Comparable 或 Comparator 来完成排序需求,这常常是繁琐的。一些童鞋可能还不知道,jdk8 为方便集合排序,在 Comparator 接口下引入了很多静态辅助方法。下面我举几例。
假如我们有一个用户类,它有 用户名、年龄、关注者 3个属性:
@Data
public class User {
String username;
int age;
List<User> followers;
}
然后我们有一组不同用户组成的集合:
List<User> users = ...
现在,我们看看如何用 Comparator 静态方法去实现不同的排序逻辑。
1. 按年龄从小到大排序:
users.sort(Comparator.comparing(User::getAge));
代码比较容易理解,取出age,根据age进行大小比较。
2. 按年龄从大到小排序:
users.sort(Comparator.comparing(User::getAge).reversed());
和示例1基本一样,只是在比较后,进行reverse操作(反向操作)。
3. 按关注者数量从小到大排序:
users.sort(Comparator.comparingInt(u -> u.getFollowers().size()));
我们不仅可以传 method reference,还可以自定义lambda。
4. 按关注者从多到少排序,若关注者数量一样,按年龄从小到大排序
users.sort(Comparator
.comparing((User u) -> u.getFollowers().size()).reversed()
.thenComparing(User::getAge));
当有多个条件时,使用 thenComparing 进行组合。
有时被排序的对象可能是null的,Comparator 也提供了 nullsFirst 和 nullsLast 方法,方便我们将null对象排在集合的首位或尾部。
另外要注意,对于复杂属性的排序,我们通常用 Comparator.comparing ,而对简单属性( primitive value,如 int、float ),建议用 Comparator.comparingInt、Comparator.comparingFloat 等,后者可避免自动装箱带来的性能损耗。
更多的使用方法,大家可参考 Comparator 源码。