JAVA排序之Comparable和Comparator

这里要讲的不是常见的譬如选择排序,冒泡排序,插入排序之类的具体算法,而是指执行这些算法时,比较俩个不同对象的“大小”操作,对于简单的整型 i > j 的操作上面的排序算法明显可行,但当我们对多个对象进行比较呢?比较的依据不是整型的数据类型呢?这样的比较 object 1 > object2 明显是不可能通过编译的,为了解决对象比较的问题,JDK提供了俩个接口 java.lang.Comparable 和 java.util.Comparator 。即自然排序和比较器排序,具体下面讲解

自然排序:java.lang.Comparable

Comparable 接口中只提供了一个方法: compareTo(Object obj) ,该方法的返回值是 int 。如果返回值为正数,则表示当前对象(调用该方法的对象)比 obj 对象“大”;反之“小”;如果为零的话,则表示两对象相等。下面是一个实现了 Comparable 接口的 Teacher 类:

public class Teacher implements Comparable<Teacher>{
    public int number;
    public String name;

    public Teacher() {
    }

    public Teacher(int number,String name) {
        this.name = name;
        this.number = number;
    }

    @Override
    public int compareTo(Teacher o) {
        if(this.number > o.number){
            return 1;
        }else if(this.number < o.number){
            return -1;
        }
        return 0;
        //也可使用下面这条语句升序排列,等效于上面的语句
        //return this.number - o.number;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        StringBuffer sb = new StringBuffer();
        sb.append(this.name+"的号码为"+this.number);
        return sb.toString();
    }

    }

实现 Comparable 就必须实现它的 compareTo 方法,这里采用的升序排列对象,可能会有点绕,可以将o看作前一对象,理解为返回1的结果即为排序方式,接下来编写测试类

    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
    import java.util.SortedSet;
    import java.util.TreeSet;

    /** *@author Mr.wei *@version 1.0 */
    public class Test {
        public static void main(String[] args) {
            Teacher t1 = new Teacher(10,"小s");
            Teacher t2 = new Teacher(13,"小h");
            Teacher t3 = new Teacher(12,"小k");
            /*使用数组*/
            Teacher t[] = new Teacher[3];
            t[0] = t1;
            t[1] = t2;
            t[2] = t3;
            Arrays.sort(t);
            /*使用List*/
    // List<Teacher> t = new ArrayList<>();
    // t.add(t1);
    // t.add(t2);
    // t.add(t3);
    // Collections.sort(t);
            for (Teacher teacher : t) {
            System.out.println(teacher.toString());
            }
        }
    }

在这里使用数组和 List 的排序调用如代码所示,但是我们注意到,排序算法和 Teacher 类绑定了, Teacher 只有一种排序算法。但现实社会不是这样的,如果我们不想按学号排序怎么办?假如,我们想按姓名来给学生排序怎么办?我们只能修改 Teacher 类的 Comparable 接口的 compareTo 方法,改成按姓名排序。如果在同一个系统里有两个操作,一个是按学号排序,另外一个是按姓名排序,这怎么办?不可能在 Teacher 类体中写两个 compareTo 方法的实现。这么看来 Comparable 就有局限性了。为了弥补这个不足,JDK 还为我们提供了另外一个排序方式,也就是下面要说的比较器排序。

比较器排序:java.util.Comparator

上面我提到了,之所以提供比较器排序接口,是因为有时需要对同一对象进行多种不同方式的排序,这点自然排序 Comparable 不能实现。另外, Comparator 接口的一个好处是将比较排序算法和具体的实体类分离了。

翻翻 API 会发现, Arrays.sort 还有种重载形式:sort(T[] a, Comparator

import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.List;
    import java.util.SortedSet;
    import java.util.TreeSet;

    /** *@author Mr.wei *@version 1.0 */
    public class Test {
        public static void main(String[] args) {
            Teacher t1 = new Teacher(10,"小s");
            Teacher t2 = new Teacher(13,"小h");
            Teacher t3 = new Teacher(12,"小k");
            Teacher t4 = new Teacher(14,"小a");
            /*使用数组*/
    // Teacher t[] = new Teacher[4];
    // t[0] = t1;
    // t[1] = t2;
    // t[2] = t3;
    // t[3] = t4;
    // Arrays.sort(t,new Comparator<Teacher>() {
    //
    // @Override
    // public int compare(Teacher o1, Teacher o2) {
    // // TODO Auto-generated method stub
    // return o1.getnumber() - o2.getnumber();
    // }
    // 
    // });

            /*使用List*/
            List<Teacher> t = new ArrayList<>();
            t.add(t1);
            t.add(t2);
            t.add(t3);
            t.add(t4);
            Collections.sort(t,new Comparator<Teacher>() {

            @Override
            public int compare(Teacher o1, Teacher o2) {
                // TODO Auto-generated method stub
                return o1.getName().compareTo(o2.getName());//按姓名排序
            }

            });
            for (Teacher teacher : t) {
            System.out.println(teacher.toString());
            }

         }
        }

这样当我们需要修改排序方式时,只需要修改 Comparator 即比较器中的返回方式即可,而我们采用匿名内部类的方法不采用实现 Comparator 接口也是为了可以把比较算法和具体类分离,降低类之间的耦合。

你可能感兴趣的:(java,排序算法)