这篇博文可以为你解决的问题如下:
  1. 什么是自然排序
  2. Collections.sort()与Arrays.sort()的异同点
  3. Comparatable接口和Comparator接口各自的排序依据(理论讲解)
  4. Comparatable接口和Comparator接口实用排序方法(实际例子分析)
  5. 综合使用Comparatable和Comparator进行整体排序
以下,我就根据上面的问题来写这篇博文:


1、什么是自然排序

    自然排序是一种升序排序。对于不同的数据类型,升序规则不一样:

  • BigDecimal BigInteger Byte Double Float Integer Long Short 类型,是按照数值的大小进行排序的。例如:12<23, 111.111>3.23
  • Character及String类型,是按照各个字符的Unicode值大小来排序的。例如:"3BC"<"AB"<"aBC"<"一二"


2、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);



从它们的定义中,我们可以看出两点:

  1. 不同点:它们适用对象不一样。
  • Collections.sort()仅适用于列表型;
  • Arrays.sort()仅适用数组类型,当然数组可以是int、float等,甚至可以是Object对象。

2. 共同点:它们都直接或间接地使用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[]进行自然排序的功能了。

3、Comparatable接口和Comparator接口各自的排序依据

引言:

    既然是排序,那就需要指定排序依据元素,且只要指定了排序依据元素,并且调用的方法得当,那么一定可以成功排序。(请牢牢记住这句话)

  • 对于单元素的类,例如:int、float、double、char、String等数据类型,排序依据元素就是它相应的这个单元素。
  • 对于多元素的类,例如:我们自定义一个Student类,它的属性有int
    age;String name;等,那么我们就需要指定一个排序依据元素。
Comparable接口的排序依据:

  • 单元素类排序。(一般是指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]);

      程序运行的结果是:(自然排序)

              

  • 多元素类排序。

首先,需要进行排序的这个多元素类(如:Student)必须实现Comparable<T>接口,且T为该多元素类的类名。

             例如:public static Student implments Comparable<Student>

       然后,在该类中(一定要在该内的内部)实现comparaTo()方法,在这里,我们将指定排序依据元素。

             例如:

            @Override

              public int compareTo(Student arg0) {

                  return arg0.getName().compareTo(this.name);//这里我们指定name为排序依据元素

              }

       最后,根据Student实例化时,是用List<Student>、还是Student[]来实现的,选择使用 Collection.sort()或Arrays.sort()进行排序。

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()方法。

4、Comparatable接口和Comparator接口实用排序方法(实际例子分析)

现在我们将用学生信息系统的排序来讲解:

  • 类名:Student
  • 属性值:long ID;String name;int age;float score;
  • 要求:根据学号、姓名或成绩升序排序所有Student实例

下面两种方法中,橘红色部分为两种方法不同的地方。

一、使用Camparable接口(共2个文件,按学号进行升序排序)



package keNan.com.stu.StudentInfomation;



public class Student implements Comparable<Student>{  

    private String ID;

    private String name;

    private int age;

    private double score;

  

    //为Student定义两个构造方法





    public Student(String ID, String name) {

        this(ID,name,0,0);

    }

    public Student(String ID, String name, int age, double score){

        this.ID = ID;

        this.name = name;

        this.age = age;

        this.score = score;

    }

   

    //属性值访问与修改

    public String getID(){

        return ID;

    }

    public String getName(){

        return name;

    }

    public int getAge(){

        return age;

    }

    public double getScore(){

        return score;

    }

  

    public void setID(String newID){

        ID = newID;

    }

    public void setName(String newName){

        name = newName;

    }

    public void setAge(int newAge){

        if(newAge < 0)

            newAge = 0;

        age = newAge;

    }

    public void setScore(double newScore){

        if( (newScore < 0 )||(newScore > 100))

            newScore = 0;

        score = newScore;

    }

   

    //重写对象字符串表示方法

    @Override

    public String toString() {

        String info = new String();

        info = ID + '\t' + name + '\t' + age + '\t' + score + '\n';

        return info;

    }



    @Override

    public int compareTo(Student arg0) {

        return this.ID.compareTo(arg0.ID);//此种写法为升序,若改为arg0.ID.compareTo(this.ID)则为降序

    }

}



package keNan.com.stu.StudentInfomation;



import java.util.Arrays;



public class StudentManage{

    public static void main(String[] args){

        //定义一个学生数据库

        final int STUDENT_NUM = 4;

        Student[] allStudents = new Student[STUDENT_NUM];

      

        //初始化学生数据库

        allStudents[0] = new Student("00001","a");

        allStudents[1] = new Student("00003","b");

        allStudents[2] = new Student("00002","c");

        allStudents[3] = new Student("00004","d");

        for(int i=0;i<allStudents.length;i++){

            allStudents[i].setAge(i*10);

        }

        for(int i=0;i<allStudents.length;i++){

            allStudents[i].setScore(99 - i*1.5);

        }

      

        //按学号升序排序

        Arrays.sort(allStudents);

       

        //显示学生信息

        System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");

        for(int i=0;i<allStudents.length;i++){

            System.out.print(allStudents[i]);

        }

    }

}

程序运行结果:





二、使用Camparator接口(共2个文件,先按姓名升序进行排序,再成绩降序排序)



package keNan.com.stu.StudentInfomation;



public class Student{  

    private String ID;

    private String name;

    private int age;

    private double score;

  

    //为Student定义两个构造方法

    public Student(String ID, String name) {

        this(ID,name,0,0);

    }

    public Student(String ID, String name, int age, double score){

        this.ID = ID;

        this.name = name;

        this.age = age;

        this.score = score;

    }

   

    //属性值访问与修改

    public String getID(){

        return ID;

    }

    public String getName(){

        return name;

    }

    public int getAge(){

        return age;

    }

    public double getScore(){

        return score;

    }

   

    public void setID(String newID){

        ID = newID;

    }

    public void setName(String newName){

        name = newName;

    }

    public void setAge(int newAge){

        if(newAge < 0)

            newAge = 0;

        age = newAge;

    }

    public void setScore(double newScore){

        if( (newScore < 0 )||(newScore > 100))

            newScore = 0;

        score = newScore;

    }

   

    //重写对象字符串表示方法

    @Override

    public String toString() {

        String info = new String();

        info = ID + '\t' + name + '\t' + age + '\t' + score + '\n';

        return info;

    }

}



package keNan.com.stu.StudentInfomation;



import java.util.Arrays;

import java.util.Comparator;



public class StudentManage{

    public static void main(String[] args){

        //定义一个学生数据库





        final int STUDENT_NUM = 4;

        Student[] allStudents = new Student[STUDENT_NUM];

       

        //初始化学生数据库

        allStudents[0] = new Student("00001","a");

        allStudents[1] = new Student("00003","b");

        allStudents[2] = new Student("00002","c");

        allStudents[3] = new Student("00004","d");

        for(int i=0;i<allStudents.length;i++){

            allStudents[i].setAge(i*10);

        }

        for(int i=0;i<allStudents.length;i++){

            allStudents[i].setScore(99 - i*1.5);

        }

       

        //按姓名升序排序

        Arrays.sort(allStudents,new ComparatorWithNameUP());

       

        //显示学生信息

        System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");

        for(int i=0;i<allStudents.length;i++){

            System.out.print(allStudents[i]);

        }

       

        //按成绩降序排序

        Arrays.sort(allStudents,new ComparatorWithScoreDown());

       

        //显示学生信息

        System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");

        for(int i=0;i<allStudents.length;i++){

            System.out.print(allStudents[i]);

        }

    }

}



//按姓名进行升序排序的外部类,用Comparator接口

class ComparatorWithNameUP implements Comparator<Student>{



    @Override

    public int compare(Student arg0, Student arg1) {

        // TODO Auto-generated method stub

        return arg0.getName().compareTo(arg1.getName());

    }   

}



//按成绩降序

class ComparatorWithScoreDown implements Comparator<Student>{



    @Override

    public int compare(Student arg0, Student arg1) {

        // TODO Auto-generated method stub

        if(arg1.getScore() > arg0.getScore())

            return 1;

        else {

            if(arg1.getScore() == arg0.getScore())

                return 0;

            else return -1;

        }

    }

   

}

程序运行结果:

5、综合使用Comparatable和Comparator进行整体排序

Comparable:

  • 优点是,对于单元素集合可以实现直接自然排序;
  • 缺点是,对于多元素排序,它的排序依据元素是固定的(compareTo()抽象方法只能实现一次),因此排序方式固定。

Comparator:

  • 优点是,元素的排序依据元素是可变的,因为可以定义N多个外部类,每个外部类实现一种排序。在不同需求下,选择不同的排序。
  • 缺点是,无论是多元素,还是单元素,都必须自己创建一个外部类来实现排序。

所以在实际运用当中,可以用Comparable的compareTo()方法来定义默认排序方式,用Comparator定义其他排序方式。

    还有一点要注意,即使Student类已经implements Comparable<Student>,但是我们在自定义外部类,如class
ComparatorWithNameUP implements Comparator<Student>,并在排序时引用sort(allStudents,new ComparatorWithNameUp());生效的排序算法是ComparatorWithNameUp.

参考资料:

  1. Comparator和Comparable比较
  2. Comparable 与 Comparator 两个接口的作用
  3. 使用TreeSet集合比较Comparable接口和Comparator接口的区别

Comparatable接口和Comparator接口的使用与区别的更多相关文章

  1. java中Comparatable接口和Comparator接口的区别

    1.不同类型的排序规则 .自然排序是什么?   自然排序是一种升序排序.对于不同的数据类型,升序规则不一样:   BigDecimal BigInteger Byte Double Float Int ...

  2. 比较器:Compare接口与Comparator接口区别与理解

    一.实现Compare接口与Comparator接口的类,都是为了对象实例数组排序的方便,因为可以直接调用 java.util.Arrays.sort(对象数组名称),可以自定义排序规则. 不同之处: ...

  3. Java中实现对象的比较:Comparable接口和Comparator接口

    在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中 ...

  4. Java6.0中Comparable接口与Comparator接口详解

    Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...

  5. Java:实现对象的比较 comparable接口和comparator接口

    在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中 ...

  6. Java—集合框架 Collections.sort()、Comparable接口和Comparator接口

    Collentions工具类--java.util.Collections Collentions是Java集合框架中,用来操作集合对象的工具类,也是Java集合框架的成员,与List.Map和Set ...

  7. Comparable接口与Comparator接口的比较————总结

    之前的两篇文章主要学习了Comparable接口和Comparator接口的学习.既然已经学习完了,现在就趁热打铁,进行总结吧! Comparable接口和Comparator接口的共同点: 1. 都 ...

  8. Java中的Comparable接口和Comparator接口

    Comparator位于包java.util下,比较器,是在集合外部定义排序.Comparable位于包java.lang下,代表当前对象可比较的,是在集合内部实现排序. Comparable代表一个 ...

  9. Java之Comparable接口和Comparator接口

    Comparable & Comparator 都是用来实现集合中元素的比较.排序的: Comparable 是在集合内部定义的方法实现的排序: Comparator 是在集合外部实现的排序: ...

随机推荐

  1. MVC3 ajax功能

    微软mvc3框架的项目使用微软自带的ajax 必须引用下面 <script src="/Scripts/jquery.unobtrusive-ajax.js" type=&q ...

  2. python字典方法

    本文参考自<python基础教程 (第二版)> 操作 语法 举例 结果 建立字典 dict() 1.以关键字参数建立字典 2.以其他映射作为参数建立字典 1.d = dict(name=' ...

  3. SPOJ - BALNUM 数位dp

    题意:求某一区间内的平衡数个数(指一个数,其中出现过的数,如果是偶数,那么必须出现奇数次,反之偶数次) 题解:用三进制来枚举(0到9)所有情况,0代表没有出现,1代表出现奇数次,2代表出现偶数次dp[ ...

  4. 51nod 1257 01分数规划/二分

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1257 1257 背包问题 V3 基准时间限制:3 秒 空间限制:1310 ...

  5. 吐槽XE3中的BUG:无法调试32位的应用程序

    我想用的功能在XE5中有BUG, 无奈转移到XE3中测试,发现了XE3还有另外一个问题:无法DEBUG 32位的应用程序,这算什么事啊?有人说把项目属性中的link with dynamic RTL去 ...

  6. Shiro安全配置

    主要还是整合了本地ehcache,集群session管理过段时间放出 <?xml version="1.0" encoding="UTF-8"?> ...

  7. 简单使用location.hash的方法 ,怎么做,有什么用? 简单的js路由页面方法。

    hash 属性是一个可读可写的字符串,该字符串是URL的锚部分(从#号开始的部分).语法location.hash刚开始我真不知道hash有什么用,直到我在项目中遇上一个最大的问题.而且很恶心的体验 ...

  8. Mysql系列:高可用(HA)-keeplived

    转自:晓叹星沉 https://my.oschina.net/blueSky4Java/blog/1572905 摘要: 随着项目的发展,为了提高程序的性能,数据库层面或多或少的会用到HA.读写分离. ...

  9. hibernate - 一级缓存和三种状态解析

    转载自:http://www.cnblogs.com/whgk/p/6103038.html 一.一级缓存和快照 什么是一级缓存呢? 很简单,每次hibernate跟数据库打交道时,都是通过sessi ...

  10. 洛谷 P3048 [USACO12FEB]牛的IDCow IDs

    题目描述 Being a secret computer geek, Farmer John labels all of his cows with binary numbers. However, ...