目录
概念
Comparable<T>接口:位于java.lang包下,需要重写public int compareTo(T o);
* str1. compareTo(str2)方法返回值是一个int类型值,当需要对某个类的对象进行排序时,该类需要实现Comparable<T>接口。如果str1=str2,返回0; str1按照字典顺序<str2,返回值<0; str1>str2,返回值>0;
- 它强行将实现它的每一个类的对象进行整体排序-----称为该类的自然排序,实现此接口的对象列表和数组可以用Collections.sort(),和Arrays.sort()进行自动排序;
- 也就是说,只要实现了这个接口的对象(数组)就相当于有了排序的能力,所以叫做comparable---可排序的,所以可以说这是一种内部排序的方式,通过实现它唯一的方法compareTo()。
Comparator<T>接口:位于java.util包下:需要重写int compare(T o1, T o2);
* 它实际上用的是待比较对象的compareTo(Object o)方法。
- 对于它,则是针对一些本身没有比较能力的对象(数组)为它们实现比较的功能,所以它叫做比较器,是一个外部的东西,通过它定义比较的方式,再传到Collection.sort()和Arrays.sort()中对目标排序,而且通过自身的方法compare()定义比较的内容和结果的升降序;
区别
Comparble接口是排序接口,Comparator是比较器。
Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
Comprable接口是通用的接口,Comparator是一种算法的实现,如果你需要在容器集合实现 比较功能,来指定它。
前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功 能的类使用。
一、Comparable<T>接口+Comparator<T>接口
参考:java基础之Compareable和Comparator的区别和使用_java_青鸟的博客-CSDN博客_compareable
现在具体的深入了解一下Comaprable接口的使用;
两个类,1:Employee类 成员属性:name/age/birthday birthday为MyDate类的对象
2:MyDate类 成员属性:month/day/year
目标:使Employee 继承Comparable 接口,并且按照name排序;
创建TreeSet ,传入Comparator对象,按照生日日期的先后顺序;
解决思路:两个类都要实现Comparable接口,使用ConpareTo()方法排序;
代码部分
Employee↓
public class Employee implements Comparable<Employee>{
@Override
public int compareTo(Employee o) {
return this.name.compareTo(o.name);
}
private String name;
private int age;
private MyDate birthday;
public Employee() {
}
public Employee(String name, int age, MyDate birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
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;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
MyDate↓
import java.util.Date;
public class MyDate implements Comparable<MyDate>{
@Override
public int compareTo(MyDate o) {
int minusYear=this.getYear() - o.getYear();
if(minusYear != 0){
return minusYear;
}
int minusMonth=this.getMonth() - o.getMonth();
if(minusMonth != 0){
return minusMonth;
}
return this.getDay() - o.getDay();
}
private int month;
private int day;
private int year;
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public MyDate() {
}
public MyDate(int year, int month, int day) {
this.month = month;
this.day = day;
this.year = year;
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
EmployeeTest↓
import org.junit.Test;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class EmployeeTest {
@Test
public void test1(){
TreeSet<Employee> set=new TreeSet<>(/*new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
MyDate b1=o1.getBirthday();
MyDate b2=o2.getBirthday();
return b1.compareTo(b2);
}
}*/);
Employee e1 = new Employee("liudehua",55,new MyDate(1965,5,4));
Employee e2 = new Employee("zhangxueyou",43,new MyDate(1987,5,4));
Employee e3 = new Employee("guofucheng",44,new MyDate(1987,5,9));
Employee e4 = new Employee("liming",51,new MyDate(1965,8,12));
Employee e5 = new Employee("liangchaowei",21,new MyDate(1978,12,4));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
for (Employee employee : set) {
System.out.println(employee);
}
System.out.println("---------------------------------");
Iterator<Employee> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
运行结果(姓名排序)↓
运行结果(生日排序)↓
加上Comparator对象按照生日排序↓
二、小Tips
编写程序时候发现,这两个compareTo()方法长得不一样,参数不同,究其原因是:
String类的compareTo()方法:
String类的compareTo()方法是用来比较两个字符串的字典顺序。
用字符串1跟字符串2作比较,如果字符串1的字典顺序在字符串2前面,则返回一个负数。若在后面,则返回一个正数。若两个字符串的字典顺序相同,则返回0。
String的源码↓↓:
原来他也是实现的Comparable接口,那其实这两个方法都是一个根,只是参数列表不同,表达的功能自然不同了。
总结
学习Comparable接口和Comparator接口本质地不同在于使用的时机,都取决于上帝视角的你,你想给这个类通过一种顺序排序,那就实现Comparable接口咯,如果你想自己我不实现Comparable接口,我想用这个像算法一样的方式去实现,那好呀,那就不用Comparable呗,直接在测试类写一个Comparator接口的实现类的对象就好了,在其中实现你想要的排序方式即可!