以下代码均基于JDK 8
在刷leetcode1的时候遇到这种问题,根据单词词频进行排序,如果词频相同,那么就按照字典排序。因为要用到比较器,而用Lambda表达式写出来的比较器比较简洁,问题如何写出复合条件下的比较器呢?
比如说,现在需要比较Human
人这个类。
public class Human {
private String name; //姓名
private int age; //年龄
// getter setter及构造函数省略
}
它具有年龄age
和名字name
两个属性,如何满足以下排序:根据年龄升序排序,如果年龄相同,那么根据名字进行字典升序排序。
实现1. 用comparator提供的方法实现
在JDK 8 及其以上版本,我们可以写出利用一级排序comparing
和次级排序thenComparing
构造如下Lambda表达式
public void sort() {
List<Human> humans = Lists.newArrayList(
new Human("Sarah", 12),
new Human("Sarah", 10),
new Human("Zack", 12)
);
humans.sort(
Comparator.comparing(Human::getName).thenComparing(Human::getAge)
);
}
实现2. 自定义排序方式
当然,我们也可以自己手写量身定制上述过程,
public void sort() {
List<Human> humans = Lists.newArrayList(
new Human("Sarah", 12),
new Human("Sarah", 10),
new Human("Zack", 12)
);
humans.sort((lhs, rhs) -> {
if (lhs.getName().equals(rhs.getName())) {
return Integer.compare(lhs.getAge(), rhs.getAge());
} else {
return lhs.getName().compareTo(rhs.getName());
}
});
}
但是如果遇到了Human的引用为Null
怎么办。我们可以在实现2中添加空值检测即可。而如果我们倒霉地选择了方法1,有什么补救措施呢?
实际上,Comparator类提供了空值处理方法nullsLast()
,它会将空值放在后面。与之相反的还有nullsFirst()
,它会把空值放在前面。
public void sortWithNull() {
List<Human> humans = Lists.newArrayList(null, new Human("Jack", 12), null);
humans.sort(Comparator.nullsLast(Comparator.comparing(Human::getName).thenComparing(Human::getAge)));
}
详细细节请参考这篇文章2