二、比较器
1、什么是比较器
在java中有两个常用的比较器,分别是Comparator接口和Comparable接口, 他们都可以完成自定义排序
,但是在使
用中,这两个比较器不管是在书写上还是侧重点上,都有不小的区别。
2、两种比较器接口的区别
Comparator 临时排序
可以在不同的排序之间切换
Comparable 永久排序
其他就不记忆了
➢Comparable接口是在lang包里的, 不需要额外导包; Comparator接口是在util包里的,需要你进行导包;
➢Comparable接口让实现 了他的子类具备某个固定的排序方式,比如String类实现 了Comparable接口之后,它的排序规
则就是一个个字母的比较;而Comparator接口是一 种比较灵活的比较方式,它属于一种临时比较的方式,我们可以在A
场景下使用这种排序,在B场景下又去使用另外一种排序;
➢Comparable接口下的方法是compareTo方法, 只有一个参数,代表的是当前对象本身与参数的比较;而Comparator接
口下的方法是compare方法,里面有两个参数,代表的是两个两个的比较;
➢Comparable接口我们都是 直接用在一个需要具有排序规则的类上,而Comparator接口我们都是以匿名内部类的形式写
在Arrays.sort和Collections.sort方法里面来临时性的对某个集合对象进行排序;
➢实现Comparable接口并且重写了排序规则的类对象可以放在TreeSet中完成排序或者是通过Arrays.sort或者是
Collections.sort完成排序,而实现Comparator接 口的临时排序规则就只用在Arrays/Collections.sort(obj,排序规则对
象)。
三、Comparable的使用
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> set4 = new TreeSet<Student>();
set4.add(new Student("zhangsan",19));
set4.add(new Student("lisi",20));
set4.add(new Student("wangwu",21));
System.out.println(set4);
}
}
class Student implements Comparable<Student>{
static int num = 0;
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
//当你返回0的时候,代表这些对象相同;
//当你返回正数的时候,代表着是该属性值的升序-->本身.属性-参数.属性
//当你返回负数的时候,代表的是该属性值的降序-->参数.属性-本身.属性
System.out.println("开始比较了第"+num+++"次");
// return o.age-this.age;
// return this.name.charAt(0)-o.name.charAt(0);
return o.name.length()-this.name.length();
}
}
/**
*
* Comparable的运用
* 1、当我们一个类已经实现了Comparable接口之后,并且重写了
* 里面的comparaTo方法时,那就证明该类已经具有了一个排序规则;
* 2、这个排序规则可以运用在以下几个场合:
* a、TreeSet;
* b、Arrays.sort;
* c、Collections.sort;
*
*/
public class ComparableDemo {
public static void main(String[] args) {
//构建一个元素是Student类型的TreeSet对象
TreeSet<Student> set = new TreeSet<Student>();
set.add(new Student("zhangsan",19));
set.add(new Student("lisi",20));
set.add(new Student("wangwu",21));
System.out.println(set);
System.out.println("--------------------------------");
//构建一个Student的数组
Student [] stus = new Student[3];
stus[0] = new Student("zhangsan",19);
stus[1] = new Student("lisi",20);
stus[2] = new Student("wangwu",21);
System.out.println(Arrays.toString(stus));
Arrays.sort(stus);
System.out.println(Arrays.toString(stus));
System.out.println("--------------------------------");
//构建一个Student的集合
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("zhangsan",19));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",21));
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
四、Comparator临时比较器的使用
-
Comparator比较器的使用
-
1、该比较器适用于临时的比较场合;
-
2、该比较器里面的方法是compare,它和Comparable里面的
compareTo里面的参数个数是不一样的,但是你可以把compare
里面的第一个参数,看成是compareTo里面的this就很容易理解了;
-
3、Comparator因为是一个临时的排序规则,所以我们一般都是在
Arrays.sort以及Collections.sort里面来使用它;不能在TreeSet里面完成排序;
-
4、我们在使用过程中,发现,一个比较规则的类只是用来使用它的一次方法的话
太过于消耗资源,那么我们能不能进行一个简化呢?使用匿名内部类
1、演示
public class ComparaTorDemo {
public static void main(String[] args) {
//构建一个Teacher的数组
Teacher [] stus = new Teacher[3];
stus[0] = new Teacher("zhangsan",19);
stus[1] = new Teacher("lisi",20);
stus[2] = new Teacher("wangwu",21);
System.out.println(Arrays.toString(stus));
Arrays.sort(stus,new MySort1());
System.out.println(Arrays.toString(stus));
System.out.println("--------------------------------");
//构建一个Teacher的集合
ArrayList<Teacher> list = new ArrayList<Teacher>();
list.add(new Teacher("zhangsan",19));
list.add(new Teacher("lisi",20));
list.add(new Teacher("wangwu",21));
System.out.println(list);
Collections.sort(list,new MySort1());
System.out.println(list);
System.out.println("--------------------------------");
// 临时体现这里,在这里使用可以将compare方法重写
Collections.sort(list,new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
return o2.name.length()-o1.name.length();
}
});
System.out.println(list);
}
}
class MySort1 implements Comparator<Teacher>{
//按照名字首字母
@Override
public int compare(Teacher o1, Teacher o2) {
return o2.name.charAt(0)-o1.name.charAt(0);
}
}
//按照名字长度排序
//class MySort implements Comparator<Teacher>{
// @Override
// public int compare(Teacher o1, Teacher o2) {
// return o2.name.length()-o1.name.length();
// }
//}
class Teacher{
int age;
String name;
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + "]";
}
}
五、案例
1.让一个字符串数组的排序规则为最后一个字母的升序。
2.完成Student类的自定义排序:
a)构建一个Student类 ,该类里面有两个属性,分别是name和age。
b)要求分别使用Comparable和Comparator来完成该类对 象的自定义排序:按照age的降序排列,
如果age相同,则按照name的升序排列。
public class Work {
public static void main(String[] args) {
work1();
work2();
}
private static void work2() {
ArrayList<Student1> list = new ArrayList<Student1>();
//Collections.addAll()
Collections.addAll(list, new Student1("zhaoliu",20),
new Student1("zhangsan",19),
new Student1("lisi",20),
new Student1("wangwu",20)
);
Collections.sort(list);
System.out.println(list);
ArrayList<Student2> list2 = new ArrayList<Student2>();
//Collections.addAll()
Collections.addAll(list2, new Student2("zhaoliu",20),
new Student2("zhangsan",19),
new Student2("lisi",20),
new Student2("wangwu",20)
);
Collections.sort(list2, new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
if(o1.age==o2.age) {
//如果年龄相同的话,那么使用name的首字母升序
return o1.name.charAt(0)-o2.name.charAt(0);
}
return o2.age-o1.age;
}
});
System.out.println(list2);
}
//1.让一个字符串数组的排序规则为最后一个字母的升序。
private static void work1() {
String [] arr = {"abc","cba","dab"};
Arrays.sort(arr,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.charAt(o1.length()-1)-o2.charAt(o2.length()-1);
}
});
System.out.println(Arrays.toString(arr));
}
}
class Student2{
String name;
int age;
public Student2(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student2 [name=" + name + ", age=" + age + "]";
}
}
class Student1 implements Comparable<Student1>{
String name;
int age;
public Student1(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
//2.完成Student类的自定义排序:
@Override
public int compareTo(Student1 o) {
if(this.age==o.age) {
//如果年龄相同的话,那么使用name的首字母升序
return this.name.charAt(0)-o.name.charAt(0);
}
return o.age-this.age;
}
}