接口Comparable
Comparable接口位于java.lang包下,需要重写public int compareTo(T o);
我们知道数字是可以用> < == 等运算符进行比较大小的,其实在字符串中也有CompareTo方法,这个方法可以用于比较字符串大小的,根据字典顺序进行排序。
Str1.compareTo(Str2);
其返回的是一个int类型值。若Str1等于参数字符串Str2字符串,则返回0;若该Str1按字典顺序小于参数字符串Str2,则返回值小于0;若Str1按字典顺序大于参数字符串Str2,则返回值大于0。
Java中很多类也都有CompareTo方法,甚至于排序算法的底层也是依赖于比较的,而这个比较就是依赖于各种数据类型的CompareTo或者Compare方法。Java中所有的compareTo方法都源于一个接口,那就是Comparable。这个接口只有一个方法,那就是CompareTo。所有想要具有比较功能的类,都建议实现这个接口,而非是自己定义这个功能,这是面向对象的概念(将具有相同功能的事物抽象到一个共同的类或接口),并且为了多态也建议通过实现接口来进行向上转型,通过接口来操作具体实现,这也是面向接口编程要求我们做的。下面我们来具体了解一下Comparable接口。
首先来分析一下String类中的CompareTo()方法和equals()方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
注意:一般情况下,compareTo和equals方法应该是统一的,equals返回true,compareTo应用返回0;所以实现了compareTo方法就要覆盖equals方法,让两者保持一致!而且前面又讲了覆盖equals方法,就一定要重写hashCode方法。
写一个People类来实现一下
public class People implements Comparable<People> {
private String name;
private Integer age;
public People() {
super();
// TODO Auto-generated constructor stub
}
public People(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 name + "_____" + age;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof People) {
People anotherPeople = (People) obj;
if (this.name.equals(anotherPeople.name)) {
return true;
}
}
return false;
}
//重写hashCode方法
@Override
public int hashCode() {
return this.name.hashCode();
}
//重写compareTo方法
@Override
public int compareTo(People people) {
if (this.age == people.age) {
// 调用String中重写的compareTo方法来比较name的大小
return this.name.compareTo(people.name);
}
return this.age - people.age;
}
}
写一个测试类来测试一下
public class ComparableTest {
public static void main(String[] args) {
//创建一个集合
ArrayList<People> arrayList = new ArrayList<>();
arrayList.add(new People("哼哼", 22));
arrayList.add(new People("小哈", 22));
arrayList.add(new People("哼哼的博客", 25));
arrayList.add(new People("哼哼", 23));
arrayList.add(new People("奋斗的哼哼", 30));
System.out.println("排序之前********************");
for (People people : arrayList) {
System.out.println(people);
}
//调用排序的方法
Collections.sort(arrayList);
System.out.println("排序之后*******************");
for (People people : arrayList) {
System.out.println(people);
}
}
}
输出结果是
排序之前********************
哼哼_____22
小哈_____22
哼哼的博客_____25
哼哼_____23
奋斗的哼哼_____30
排序之后*******************
哼哼_____22
小哈_____22
哼哼_____23
哼哼的博客_____25
奋斗的哼哼_____30
接口Comparator
Comparator接口位于java.util包下:需要重写int compare(T o1, T o2);
- 我们需要控制某个类的次序,而该类不支持排序(即没有实现Comparable接口)。那么,我们可以创建一个该类的比较器,这个比较器只需要实现Comparator。若一个类实现了Comparator接口,则它一定要实现compare(T o1,T o2)方法,但不一定要实现equals(Object obj)方法;
- 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过Comparator来实现比较算法进行排序;为了使用不同的排序标准做准备,比如:升序、降序
在上面的例子基础上,使用一些接口Comparator,然后用输出一下!
@Override
public int compare(People2 people1, People2 people2) {
if(people1.age-people2.age==0) {
return people1.name.compareTo(people2.name) ;
}
return people1.age-people2.age;
}
//测试类
public class ComparableTest {
public static void main(String[] args) {
//创建一个集合
ArrayList<People2> arrayList = new ArrayList<>();
arrayList.add(new People2("哼哼", 22));
arrayList.add(new People2("小哈", 22));
arrayList.add(new People2("哼哼的博客", 25));
arrayList.add(new People2("哼哼", 23));
arrayList.add(new People2("奋斗的哼哼", 30));
System.out.println("排序之前********************");
for (People2 people : arrayList) {
System.out.println(people);
}
//调用排序的方法
Collections.sort(arrayList,new People2());
System.out.println("排序之后*******************");
for (People2 people : arrayList) {
System.out.println(people);
}
}
}
输出结果
排序之前********************
哼哼_____22
小哈_____22
哼哼的博客_____25
哼哼_____23
奋斗的哼哼_____30
排序之后*******************
哼哼_____22
小哈_____22
哼哼_____23
哼哼的博客_____25
奋斗的哼哼_____30
Compareable和Comparator两者比较总结:
- Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”;而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
- Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
- Comparable是通用的接口,用户可以实现它来完成自己特定的比较,而Comparator可以看成是一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成是一种设计模式,将算法和数据分离。
- 前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用