Comparable是排序接口: 若一个类实现了Comparable接口,就意味着“该类支持排序”。
Comparator是比较器: 我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
我们需要创建一个包含了用户列表的 List 集合,并按用户的年龄从大到小进行排序,具体实现代码如下: 第一种:实现Comparable<>接口
写一个Person类:
class Person implements Comparable<Person>{
Integer id;
String name;
Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Person o) {
//按照年龄从大到小排序
return o.getAge()-this.getAge();
}
}
实现结果测试:
public static void main(String[] args){
//假设放进去三个对象,直接调用
List<Person> pr=new ArrayList<Person>(){{
add(new Person(1,"huitao1",32));
add(new Person(2,"huitao2",40));
add(new Person(3,"huitao3",28));
}};
//很重要
Collections.sort(pr);
pr.forEach(p->{
System.out.print(p);
});
}
结果按照40、32、28进行了排序
第二种: Comparator 排序
Comparable 是类内部的比较方法,而 Comparator 是排序类外部的比较器。使用 Comparator 比较器,无需修改原 Person 类,只需要扩充一个 Person 类的比较器就行了,Comparator 的实现方法有以下两种:
- 新建 Comparator 比较器;
- 使用 Comparator 匿名类比较器。
static class Person {
Integer id;
String name;
Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
编写一个比较器类:
static class ToPerson implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
public static void main(String[] args){
List<Person> pr=new ArrayList<Person>(){{
add(new Person(1,"huitao1",32));
add(new Person(2,"huitao2",40));
add(new Person(3,"huitao3",28));
}};
//很重要
Collections.sort(pr,new ToPerson());
pr.forEach(p->{
System.out.print(p);
});
}
测试结果:
分别为28、32、40,如果要从大到小,可以编写为
static class ToPerson implements Comparator<Person>{ @Override public int compare(Person o1, Person o2) { return o2.getAge() - o1.getAge(); } }
以匿名类的方式访问:
static class Person {
Integer id;
String name;
Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args){
List<Person> pr=new ArrayList<Person>(){{
add(new Person(1,"huitao1",32));
add(new Person(2,"huitao2",40));
add(new Person(3,"huitao3",28));
}};
//很重要
Collections.sort(pr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
});
pr.forEach(p->{
System.out.print(p);
});
}
第三种:使用 Stream 流排序
public static void main(String[] args){
List<Person> pr=new ArrayList<Person>(){{
add(new Person(1,"huitao1",32));
add(new Person(2,"huitao2",40));
add(new Person(3,"huitao3",28));
}};
pr= pr.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
pr.forEach(p->{
System.out.print(p);
});
}
static class Person {
Integer id;
String name;
Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
stream()如果排序属性出现null,报告空指针个错误,解决办法
public static void main(String[] args){
List<Person> pr=new ArrayList<Person>(){{
add(new Person(1,"huitao1",32));
add(new Person(2,"huitao2",40));
add(new Person(3,"huitao3",28));
add(new Person(4,"huitao3",null));
}};
pr= pr.stream().sorted(Comparator.comparing(Person::getAge,Comparator.nullsFirst(Integer::compareTo)).reversed()).collect(Collectors.toList());
pr.forEach(p->{
System.out.print(p);
});
}
static class Person {
Integer id;
String name;
Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
Comparator.nullsFirst 表示将排序字段中的 null 值放到集合最前面,如果想要将 null 值放到集合最后面可以使用 Comparator.nullsLast。