在 Java 类库中,有很多针对数组和 List 的排序方法,比如 Arrays.sort() 、Collections.sort() ,以及在 Java 8中 List 接口新加的默认方法 sort() 。而 sort 最主要的使用方式有两种,具体可以参考博客:Java中comparable 和 comparator
在本文中我们的重点放在 Comparator 的使用上面,因为通过它,我们可以清楚看到Lambda表达式的使用方式。首先贴出代码:
import java.util.*;
// 静态导入
import static java.util.Comparator.comparing;
class Human implements Comparable<Human>{
private String name;
private int age;
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Human o) {
return this.age - o.getAge();
}
}
public class ComparatorDemo {
public static void main(String[] args) {
List<Human> humans = new ArrayList<>();
humans.add(new Human("Sarah", 10));
humans.add(new Human("Jack", 12));
humans.add(new Human("Jack", 10));
/**
* Arrays.sort只能针对数组类型进行排序
*/
Human[] arrayHumans = (Human[]) humans.toArray();
Arrays.sort(arrayHumans, new Comparator<Human>() {
@Override
public int compare(Human o1, Human o2) {
return o1.getAge() - o2.getAge();
}
});
/**
* Arrays.sort的Comparator匿名类使用 lambda表达式 进行表示
*/
Arrays.sort(arrayHumans, (o1, o2) -> o1.getAge() - o2.getAge());
/**
* 将lambda表达式进一步使用 方法引用 的方式进行表示
* 不过这种方式只能按照 age 进行升序排序,如果lambda表达式是:
* (o1, o2) -> o2.getAge() - o1.getAge()
* 就不能使用comparingInt方法了
*/
Arrays.sort(arrayHumans, Comparator.comparingInt(Human::getAge));
/**
* 使用Collections对list进行排序,其实Collections.sort依然使用的是Arrays.sort
*
*/
Collections.sort(humans, new Comparator<Human>() {
@Override
public int compare(Human o1, Human o2) {
return o1.getAge() - o2.getAge();
}
});
/**
* 同样使用lambda表达式来替换Comparator匿名类
*/
Collections.sort(humans, (o1, o2) -> o1.getAge() - o2.getAge());
/**
* 使用 方法引用 的方式
* 只能默认升序
*/
Collections.sort(humans, Comparator.comparingInt(Human::getAge));
/**
* 降序不能使用comparing静态方法
*/
Collections.sort(humans, (h1, h2) -> h2.getAge() - h1.getAge());
/**
* 使用List接口中的默认方法sort进行
* 底层同样是Arrays.sort方法
*/
humans.sort(new Comparator<Human>() {
@Override
public int compare(Human o1, Human o2) {
return o1.getAge() - o2.getAge();
}
});
/**
* lambda表达式排序
*/
humans.sort((h1,h2) -> h1.getAge() - h2.getAge());
/**
* 方法引用 的方式
* 升序
*/
humans.sort(Comparator.comparingInt(Human::getAge));
/**
* 降序排序
*/
humans.sort((h1, h2) -> h2.getAge() - h1.getAge());
/**
* 根据 name 进行升序排序
* 使用了静态导入的功能
*/
humans.sort(comparing(Human::getName));
/**
* 根据 name 进行降序排序
* 使用了静态导入的功能
*/
humans.sort(comparing(Human::getName).reversed());
/**
* 根据 name 和 age 组合排序
* 如果 name 相等,则比较 age
*/
humans.sort(new Comparator<Human>() {
@Override
public int compare(Human o1, Human o2) {
if (o1.getName().equals(o2.getName()))
return o1.getAge() - o2.getAge();
return o1.getName().compareTo(o2.getName());
}
});
/**
* 根据 name 和 age 组合排序
* lambda表达式的形式
*/
humans.sort((o1, o2) -> {
if (o1.getName().equals(o2.getName()))
return o1.getAge() - o2.getAge();
return o1.getName().compareTo(o2.getName());
});
/**
* 根据 name 和 age 组合排序
* 方法引用的形式
*/
humans.sort(comparing(Human::getName).thenComparing(Human::getAge));
}
}
上面的代码主要涉及了三种排序方式:Arrays.sort()、Collections.sort() 以及 List接口中默认方法的使用。
而每种 sort 方法中又都分别使用了 Comparator 的匿名实现类、Lambda表达式和方法引用的实现方式。方法引用的方式使用了Comparator类中的静态方法 comparing 和 comparingInt。
使用 Comparator 中的静态方法还可以更方便进行组合排序,详见上面代码和注释。