接口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);

  1. 我们需要控制某个类的次序,而该类不支持排序(即没有实现Comparable接口)。那么,我们可以创建一个该类的比较器,这个比较器只需要实现Comparator。若一个类实现了Comparator接口,则它一定要实现compare(T o1,T o2)方法,但不一定要实现equals(Object obj)方法;
  2. 如果类的设计师没有考虑到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两者比较总结:

  1. Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”;而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
  2. Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
  3. Comparable是通用的接口,用户可以实现它来完成自己特定的比较,而Comparator可以看成是一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成是一种设计模式,将算法和数据分离。
  4. 前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用