比较器comparable和comparator的区别
Java提供了一个集合工具类,里面有排序方法,Collections使用它提供的方法来完成排序
注意:Collection不是Collections,Collections是在Collection上进行操作的集合的一个工具类,就如Arrays是数组的工具类
public class ComparableTest {
public static void main(String[] args) {
String names[] = { "Jack", "Adam", "Bob" };
List<String> list = Arrays.asList(names);
System.out.println(list);
//排序的方式String已经替我们完成了
//String会调用compareTo()方法实现排序的功能
Collections.sort(list);
System.out.println(list);
}
}
String类实现Comparable接口,当调用sort规则时,String会调用compareTo方法实现排序功能
public class StudentComparable {
public static void main(String[] args) {
Student stu[] = {
new Student("005", "Jackson", 3, 3, "football"),
new Student("001", "Jerry", 1, 3, "football"),
new Student("002", "Adam", 5, 2, "Tennis")
};
//错误原因:1Student没有实现Comparable接口
// 2 没有指定排序规则(id、name、hobby)
List<Student> list = Arrays.asList(stu);
//如何比较排序? Collections.sort方法进行排序,它会回调 容器中Student对象的 compareTo方法
Collections.sort(list);
for(Student student : list){
System.out.println(student);
}
}
}
public class Student implements Comparable<Student>{
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public int getClassNo() {
return classNo;
}
public void setClassNo(int classNo) {
this.classNo = classNo;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", grade=" + grade + ", classNo=" + classNo + ", hobby=" + hobby
+ "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + classNo;
result = prime * result + grade;
result = prime * result + ((hobby == null) ? 0 : hobby.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (classNo != other.classNo)
return false;
if (grade != other.grade)
return false;
if (hobby == null) {
if (other.hobby != null)
return false;
} else if (!hobby.equals(other.hobby))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Student(String id,String name,int grade,int classNo,String hobby) {
this.id =id;
this.name = name;
this.grade = grade;
this.classNo = classNo;
this.hobby = hobby;
}
private String id;
private String name;
private int grade;
private int classNo;
private String hobby;
/**
* Comparable 的compareTo方法为我们提供了比较的功能,
* 如何比较
* 怎么做需要在Student类中实现
* 我的规则:按照学生的ID进行排序
*/
@Override
public int compareTo(Student o) {
//两个对象需要做比较
//this的id 如果大于 o 的id 返回的是正数
//this的id 如果等于 o 的id 返回的是0
//this的id 如果小于 o 的id 返回的是负数
// int result = -(this.getId().compareTo(o.getId()));
// return result;
// if(this.getId().compareTo(o.getId()) >0){
// return 1;
// }else if(this.getId().compareTo(o.getId())<0){
// return -1;
// }
// return 0;
//按照年级进行排序
if(this.getGrade() > o.getGrade()){
return 1;
}else if(this.getGrade() < o.getGrade()){
return -1;
}
return 0;
}
//制定一个策略:输入1 id 输入2 name 输入3 爱好排序
}
如果只比较一次 ,可以使用匿名内部类节约资源
public class CheLueCompator {
public static void main(String[] args) {
Student stu[] = {
new Student("005", "Jackson", 3, 6, "football"),
new Student("001", "Zero", 1, 3, "basketball"),
new Student("002", "Adam", 5, 2, "tennis")
};
List<Student> list = Arrays.asList(stu);
sortList(list);
}
public static void sortList(List<Student> list) {
Scanner input = new Scanner(System.in);
System.out.println("请输入排序编号 1按照学生名称 2按照爱好 3按照班级编号");
int num = input.nextInt();
switch (num) {
case 1:
//两个参数 1需要排序的列表 2排序的策略 (按照名称排序)
//匿名内部类:接口回调(由谁回调谁?)sort方法回调匿名内部类
//好莱坞原则:sort理解为好莱坞 ,匿名内部类理解为演员
//你不要找我,如果有需要我来找你,前提(匿名内部类需要向好莱坞进行注册)
//如何注册(匿名内部类作为参数传入sort方法),sort方法需要的时候会回调匿名内部类的方法
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//调用String的compareTo()方法
return o1.getName().compareTo(o2.getName());
}
});
break;
case 2:
Collections.sort(list,new StuHobbyCompator());
break;
case 3:
Collections.sort(list,new StuClassNoCompator());
break;
default:
System.out.println("Error");
break;
}
input.close();
iteratorStu(list);
}
public static void iteratorStu(List<Student> list) {
for(Student student : list){
System.out.println(student);
}
}
}
Comparable和Comparator的区别
1、Comparable:在java.lang包,通常由实体类(Student)来实现,用来定义默认的排序规则
StudentComparable.java回调容器中Student对象的 compareTo方法
Comparator:在java.util包,排序的工具类,是一种策略,通常一个实体类(Student)有一种默认的排序法,还有多种排序策略
Comparable 定义在 Person类的内部:
public class Persion implements Comparable {..比较Person的大小..},
因为已经实现了比较器,那么我们的Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样
2、Comparator
Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化,如
public class Person{ String name; int age },
然后我们另外定义一个比较器:
public PersonComparator implements Comparator() {..比较Person的大小..},
用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
在PersonComparator里面实现了怎么比较两个Person的大小. 所以,用这种方法,当我们要对一个 personList进行排序的时候, 我们除了了要传递personList过去, 还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator里面实现的, 如:
Collections.sort( personList , new PersonComparator() ).
一个是自已完成比较,一个是外部程序实现比较的差别而已。
3、Comparator 和 Comparable 的实例
实现Comparable接口要覆盖compareTo方法, 在compareTo方法里面实现比较
public class Person implements Comparable {
String name;
int age
public int compareTo(Person another) {
int i = 0;
i = name.compareTo(another.name); // 使用字符串的比较
if(i == 0) { // 如果名字一样,比较年龄, 返回比较年龄结果
return age - another.age;
} else {
return i; // 名字不一样, 返回比较名字的结果.
}
}
}
这时我们可以直接用 Collections.sort( personList ) 对其排序了.
实现Comparator需要覆盖 compare 方法:
public class Person{
String name;
int age
}
class PersonComparator implements Comparator {
public int compare(Person one, Person another) {
int i = 0;
i = one.name.compareTo(another.name); // 使用字符串的比较,即调用String的比较丰富
if(i == 0) { // 如果名字一样,比较年龄,返回比较年龄结果
return one.age - another.age;
} else {
return i; // 名字不一样, 返回比较名字的结果.
}
}
}
Collections.sort( personList , new PersonComparator()) 可以对其排序
4、总结
两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码, 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。