Java:简述排序之Comparatable接口和Comparator接口

Java:简述排序之Comparatable接口和Comparator接口


一.自然排序是什么?
   自然排序是一种升序排序。对于不同的数据类型,升序规则不一样:
   BigDecimal,BigInteger,Byte,Double,Float,Integer,Long,Short 类型,是按照数值的大小进行排序的。例如:12<23, 111.111>3.23
   Character及String类型,是按照各个字符的Unicode值大小来排序的。例如:"3BC"<"AB"<"aBC"<"一二"

二.Collections.sort()与Arrays.sort()的异同点
   Collections.sort()的定义只有以下两个:

public static <T extends Comparable<? super T>> void sort(List<T> list);

public static <T> void sort(List<T> list, Comparator<? super T> c);

   Arrays.sort()的定义有很多,这里列出有代表性的三个:

public static void sort(int[] a);
public static void sort(Object[] a);
public static <T> void sort(T[] a, Comparator<? super T> c);

   从上述的定义中,我们可以看出两点:
      不同点:它们适用对象不一样。
            Collections.sort()仅适用于列表型;
            Arrays.sort()仅适用数组类型,当然数组可以是int、float等,甚至可以是Object对象。
      共同点:它们都直接或间接地使用Comparatable接口或Comparator接口。
            Collections.sort()很明显地引用了这两个接口;
            Arrays.sort()中,其实,int、float等对应的封装类Integer、Float等class中,都有实现对接口Comparable的引用,例如:Integer的定义如下:

public final class Integer extends Number implements Comparable<Integer>

            Comparable接口在默认情况下,具有自然排序功能。所以,当我们使用Arrays.sort(int[])时,就已经实现了对int[]进行自然排序的功能了。

三.Comparatable接口和Comparator接口各自的排序依据
   
既然是排序,那就需要指定排序依据元素,且只要指定了排序依据元素,并且调用的方法得当,那么一定可以成功排序。
    对于单元素的类,例如:int、float、double、char、String等数据类型,排序依据元素就是它相应的这个单元素。
    对于多元素的类,例如:我们自定义一个Student类,它的属性有int age;String name;等,那么我们就需要指定一个排序依据元素。
    1.Comparable接口的排序依据:
        A.单元素类排序:(一般是指Java中已经实现Comparable接口的类,常用的有:Integer、Float、Double、String、Character等),这些类已经有了排序依据元素,所以可以直接排序。因此,在排序中,我们可以这样做:(以int为例)

int[] intArray = {12,34,0,5,-7,8,1,3};
Arrays.sort(intArray); //这里就是直接依据int值的大小来排序的

for(int i=0;i<intArray.length;i++) {
    System.out.println(intArray[i]);
}

        程序运行的结果是:(自然排序)-7,0,1,3,5,8,12,34
        B.多元素类排序:
            首先,需要进行排序的这个多元素类(如:Student)必须实现Comparable<T>接口,且T为该多元素类的类名。
                    例如:public static Student implments Comparable<Student>
            然后,在该类中(一定要在该内的内部)实现comparaTo()方法,在这里,我们将指定排序依据元素。
                    例如:

@Override
public int compareTo(Student arg0) {
    //这里我们指定name为排序依据元素
    return arg0.getName().compareTo(this.name);
}

            最后,根据Student实例化时,是用List<Student>、还是Student[]来实现的,选择使用 Collection.sort()或Arrays.sort()进行排序。
    2.Comparator接口的排序依据:
        与Comparable不同的是,要实现Comparator接口,一定要在程序中指定排序依据元素(不管是单元素,还是多元素)。而且,这个实现Comparator接口的类一定要在排序的类(如Student)之外。可以是匿名类,如:

Collection.sort(allStudents,new Comparator<Student>() {
    public int compare(Student one, Student another) {
        return one.getAge() - another.getAge();
    }
});

        也可以是一个外部类,如class StudentSort implments<Student>{};的实例,Collention.sort(allStudent,new StudentSort());
   小结:Comparatable接口必须由需要排序的多元素类本身来实现,且在其内部重写comparaTo()方法;Comparator接口是在需要排序的多元素类的外部(即使用外部类)来实现,且必须在该外部类中重写compara()方法。

四.综合使用Comparatable和Comparator进行整体排序
   1.Comparable:
         优点是,对于单元素集合可以实现直接自然排序;
         缺点是,对于多元素排序,它的排序依据元素是固定的(compareTo()抽象方法只能实现一次),因此排序方式固定。
   2.Comparator:
         优点是,元素的排序依据元素是可变的,因为可以定义N多个外部类,每个外部类实现一种排序。在不同需求下,选择不同的排序。
         缺点是,无论是多元素,还是单元素,都必须自己创建一个外部类来实现排序。
   所以在实际运用当中,可以用Comparable的compareTo()方法来定义默认排序方式,用Comparator定义其他排序方式。
   注意:即使Student类已经implements Comparable<Student>,但是我们在自定义外部类,如class ComparatorWithNameUP implements Comparator<Student>,并在排序时引用sort(allStudents,new ComparatorWithNameUp());生效的排序算法是ComparatorWithNameUp。

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页