Comparable<T>
和 Comparator<T>
这俩接口经常被使用,这里介绍下这俩是什么以及怎么用
Comparable<T>和Comparator<T>一般都是用来排序对象的,
Comparable<T>是内部比较器,Comparator<T>是外部比较器,直接上代码看例子
Comparable<T>
Comparable<T>
内部比较器,故那个类需要排序能力就实现它
1.如果我们想让List<SortA>按一定方式排序,可以将SortA实现 Comparable<SortA>
接口,重写compareTo(SortA s)
方法
@Data
public class SortA implements Serializable, Comparable<SortA>{
@ApiModelProperty("名字")
private String name;
@ApiModelProperty("年龄")
private Integer age;
//自定义排序规则
@Override
public int compareTo(SortA o) {
return this.age - o.getAge(); //升序
//return this.age.compareTo( o.getAge()); //升序
//return o.getAge() - this.age; //倒序
//return o.getAge().compareTo(this.age); //倒序
//return -1; //自然排序的倒序
//return 1 或 0; //自然排序
}
}
public class 排序 {
public static void main(String[] args) {
//创造数据
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a张三");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("c李四");
a2.setAge(16);
SortA a3 = new SortA();
a3.setName("b王五");
a3.setAge(17);
listA.add(a1);
listA.add(a2);
listA.add(a3);
//调用方法
testComparable(listA);
}
public static void testComparable(List<SortA> listA) {
//排序方法Collections.sort(List<T> list);
//内部使用 Arrays.sort(a, (Comparator) c);
//所以如果数据是是数组,可以直接用Arrays.sort(数据)来排序
Collections.sort(listA);
System.out.println("Comparable排序:" + listA);
//Comparable排序:[SortA(name=李四, age=16), SortA(name=王五, age=17), SortA(name=张三, age=18)]
}
}
我们可以发现Comparable<T>
代码侵入性比较强,而且不够灵活,我们同一对象每次排序的规则不可能都一样,那么就可以外部比较器Comparator<T>
2.1 Comparator可以不由SortA实现,可以实现一个SortAComparator排序类
//注意泛型是需要排序的类SortA
public class SortAComparator implements Comparator<SortA> {
/**
* compare()和compareTo()很像,返回值参照compareTo(),o1相当于this
*/
@Override
public int compare(SortA o1, SortA o2) {
int sort = o1.getAge() - o2.getAge();
return sort;
}
}
2.2 Comparable是一个函数式接口,所以可以使用匿名内部类或者Lambda表达式(常用)来实现
甚至jdk8以后Comparable<T>提供了很多static方法直接供我们使用
2.3 直接上代码
public class 排序 {
public static void main(String[] args) {
//创造数据
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a张三");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("c李四");
a2.setAge(16);
SortA a3 = new SortA();
a3.setName("b王五");
a3.setAge(17);
listA.add(a1);
listA.add(a2);
listA.add(a3);
//调用方法
testComparator(listA);
}
public static void testComparator(List<SortA> listA) {
//外部比较器,实现Comparator接口
//1.SortAComparator实现Comparator接口
listA.sort(new SortAComparator());
System.out.println(listA);
//2.使用匿名内部类或Lambda,表达式
listA.sort(new Comparator<SortA>() {
@Override
public int compare(SortA o1, SortA o2) {
//年龄倒序
return o2.getAge() - o1.getAge();
}
});
//3.使用匿名内部类或Lambda或Comparator的静态方法"
//3.1按照名字正序排序
listA.sort(Comparator.comparing(SortA::getName));
System.out.println(listA);
//3.2按照名字倒序排序
listA.sort(Comparator.comparing(SortA::getName).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()));
System.out.println(listA);
}
}
reversed和Comparator.reverseOrder()反转顺序的时机不同
Comparator.reverseOrder()会立即对此属性排序
reversed()会得到左边的结果后在排序
所以
Comparator.reverseOrder()是只针对当前属性的反转,
reversed()会使左边所有排序反转,注意这一点就行了
public class 排序 {
public static void main(String[] args) {
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("a");
a2.setAge(19);
SortA a3 = new SortA();
a3.setName("b");
a3.setAge(17);
SortA a4 = new SortA();
a4.setName("c");
a4.setAge(17);
SortA a5 = new SortA();
a5.setName("d");
a5.setAge(15);
listA.add(a1);
listA.add(a2);
listA.add(a3);
listA.add(a4);
listA.add(a5);
moreComparator(listA);
}
public static void moreComparator(List<SortA> listA){
//1.name正序,name一样age正序
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge));
System.out.println(listA);
//2.name倒序,name一样age正序
listA.sort(Comparator.comparing(SortA::getName).reversed().thenComparing(SortA::getAge));
System.out.println(listA); listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()).thenComparing(SortA::getAge));
System.out.println(listA);
//3.name倒序,name一样age倒序
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()).thenComparing(SortA::getAge,Comparator.reverseOrder()));
System.out.println(listA);
//4.name正序,name一样age倒序
listA.sort(Comparator.comparing(SortA::getName).reversed().thenComparing(SortA::getAge).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge,Comparator.reverseOrder()));
System.out.println(listA);
}
}
public class 排序 {
public static void main(String[] args) {
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("a");
a2.setAge(19);
SortA a3 = new SortA();
a3.setName("b");
a3.setAge(17);
SortA a4 = new SortA();
a4.setName("c");
a4.setAge(17);
SortA a5 = new SortA();
// a5.setName("d");
a5.setAge(15);
listA.add(a1);
listA.add(a2);
listA.add(a3);
listA.add(a4);
listA.add(a5);
listA.add(null);
nullComparator(listA);
}
//如果对象或者属性为空
public static void nullComparator(List<SortA> listA){
//1.如果对象为空
listA.sort(Comparator.nullsFirst(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.naturalOrder()))));
System.out.println(listA);
//2.如果name为空
//自然排序
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.naturalOrder())));
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(String::compareTo)));
System.out.println(listA);
//反转
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.reverseOrder())));
System.out.println(listA);
}
}
Comparable<T>
是内部比较器,Comparator<T>
是外部比较器
最推荐使用Comparator<T>
接口排序
Comparator
提供静态方法很方便,推荐使用,不了解的可以先去学习函数式接口、Lambda、方法引用
Comparator
多条件排序时注意Comparator.reverseOrder()和reversed()的使用,
Comparator
排序时注意对象和属性可能为空的情况,使用Comparator.nullsFirst()或者Comparator.nullsLast()