精华内容
下载资源
问答
  • java中自然排序和比较器排序
    千次阅读
    2016-09-19 13:29:13

     这里所说到的Java中的排序并不是指插入排序、希尔排序、归并排序等具体的排序算法。而是指执行这些排序算法时,比较两个对象“大小”的比较操作。我们很容易理解整型的 i>j 这样的比较方式,但当我们对多个对象进行排序时,如何比较两个对象的“大小”呢?这样的比较 stu1 > stu2 显然是不可能通过编译的。为了解决如何比较两个对象大小的问题,JDK提供了两个接口 java.lang.Comparable 和 java.util.Comparator 。

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

    Java代码 收藏代码
    public class Student implements Comparable {

    private int id;  
    
    private String name;  
    
    public Student() {  
        super();  
    }  
    
    @Override  
    public int compareTo(Object obj) {  
        if (obj instanceof Student) {  
            Student stu = (Student) obj;  
            return id - stu.id;  
        }  
        return 0;  
    }  
    
    @Override  
    public String toString() {  
        return "<" + id + ", " + name + ">";  
    }  
    

    }

      Student 实现了自然排序接口 Comparable ,那么我们是怎么利用这个接口对一组 Student 对象进行排序的呢?我们在学习数组的时候,使用了一个类来给整型数组排序: java.util.Arrays 。我们使用 Arrays 的 sort 方法来给整型数组排序。翻翻 API 文档就会发现, Arrays 里给出了 sort 方法很多重载形式,其中就包括 sort(Object[] obj) ,也就是说 Arryas 也能对对象数组进行排序,排序过程中比较两个对象“大小”时使用的就是 Comparable 接口的 compareTo 方法。

    Java代码 收藏代码
    public class CompareTest {

    public static void main(String[] args) {  
        Student stu1 = new Student(1, "Little");  
        Student stu2 = new Student(2, "Cyntin");  
        Student stu3 = new Student(3, "Tony");  
        Student stu4 = new Student(4, "Gemini");  
    
        Student[] stus = new Student[4];  
        stus[0] = stu1;  
        stus[1] = stu4;  
        stus[2] = stu3;  
        stus[3] = stu2;  
        System.out.println(“Array: ” + Arrays.toString(stus));   
        Arrays.sort(stus);   
        System.out.println(“Sort:  ” + Arrays.toString(stus));  
    }  
    

    }

      Student 数组里添加元素的顺序并不是按学号 id 来添加的。调用了 Arrays.sort(stus) 之后,对 Student 数组进行排序,不管 sort 是使用哪种排序算法来实现的,比较两个对象“大小”这个操作,它是肯定要做的。那么如何比较两个对象的“大小”? Student 实现的 Comparable 接口就发挥作用了。 sort 方法会将待比较的那个对象强制类型转换成 Comparable ,并调用 compareTo 方法,根据其返回值来判断这两个对象的“大小”。所以,在这个例子中排序后的原 Student 乱序数组就变成了按学号排序的 Student 数组。

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

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

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

    更多相关内容
  • 给大家介绍Java中的排序并不是指插入排序、希尔排序、归并排序等具体的排序算法。而是自然排序和比较器排序,文中通过实例代码介绍的很详细,有需要的朋友们可以参考借鉴。
  • Java中的自然排序和比较器排序

    千次阅读 2019-01-13 14:53:28
    写在前面的话:刚开始学习着两者排序时我也是一头雾水,虽然能写出来但是稀里糊涂,几时该用哪个排序一点想法都没有,后来经过研究这两者的作用点不同,自然排序作用在实体类上,而比较器排序作用在装实体类的集合上...

    写在前面的话:刚开始学习着两者排序时我也是一头雾水,虽然能写出来但是稀里糊涂,几时该用哪个排序一点想法都没有,后来经过研究这两者的作用点不同,自然排序作用在实体类上,而比较器排序作用在装实体类的集合上。

    1、自然排序:java.lang.Comparable 

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

    总结为一句话:实现Comparable,重写 compareTo方法

    案列:以TreeMap为例,默认的升序,可以重写自然排序的方法改变原有排序

    public static void testComparable(){
            TreeMap<Car,Object> tmp = new TreeMap<Car,Object>();
            tmp.put(new Car(4), "肆");
            tmp.put(new Car(1), "壹");
            tmp.put(new Car(5), "伍");
            tmp.put(new Car(3), "三");
            tmp.put(new Car(2), "贰");
            System.out.println(tmp);
            //结果://{Car [price=5.0]=伍, Car [price=4.0]=肆, Car [price=3.0]=三, Car [price=2.0]=贰, Car [price=1.0]=壹}
        }

    //自定义TreeMap排序方法    自然排序   

    class Car implements Comparable<Car>{
        private double price;
        
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public Car(int price) {
            super();
            this.price = price;
        }
    
    
        @Override
        public int compareTo(Car o) {
            // TODO Auto-generated method stub
            if(this.price>o.getPrice()){
                return -1;//大的往前排
            }else if(this.price<o.getPrice()){
                return 1;//小的往后排
            }else{
                return 0;
            }
        }
    
        @Override
        public String toString() {
            return "Car [price=" + price + "]";
        }

    2、比较器排序:java.util.Comparator 

    总结为一句话:实现Comparator 接口,重写compare方法

    public static void testComparator(){
            //HashMap<Integer,Object> hm = new HashMap<Integer,Object>();
            TreeMap<Integer,Object> tmp = new TreeMap<Integer,Object>(new MyComparatorBigtoSmall());
            tmp.put(4, "肆");
            tmp.put(1, "壹");
            tmp.put(5, "伍");
            tmp.put(3, "三");
            tmp.put(2, "贰");
            //System.out.println(tmp);//默认排序结果:{1=壹, 2=贰, 3=三, 4=肆, 5=伍}
            System.out.println(tmp);//修改为比较器排序(升序){5=伍, 4=肆, 3=三, 2=贰, 1=壹}
        }
    
    //自定义TreeMap排序方法    比较器排序    
        class MyComparatorBigtoSmall implements Comparator<Integer>{
    
            @Override
            public int compare(Integer o1, Integer o2) {
                // TODO Auto-generated method stub
                return o2-o1;
            }
        }

    如需了解两者的详细介绍,请点击https://blog.csdn.net/lichaohn/article/details/5389276

    展开全文
  • TreeSet集合TreeSet集合是Set集合的一个子实现类,它是基于TreeMap中的NavigableSet接口实现的TreeSet集合是默认通过自然排序将集合中的元素进行排序TreeSet有两种排序方式:1)自然排序2)比较器排序让我们先来看看...

    TreeSet集合

    TreeSet集合是Set集合的一个子实现类,它是基于TreeMap中的NavigableSet接口实现的

    TreeSet集合是默认通过自然排序将集合中的元素进行排序

    TreeSet有两种排序方式:

    1)自然排序

    2)比较器排序

    让我们先来看看一个例题:

    package com.TreeSetDome;
     
    import java.util.TreeSet;
     
    public class TreeSetDome {
     
    public static void main(String[] args) {
    TreeSet<Integer> set=new TreeSet<Integer>();
    set.add(17);
    set.add(25);
    set.add(23);
    set.add(14);
    set.add(17);
    set.add(30);
    for(Integer s:set) {
    System.out.println(s);
    }
    }
    }
    运行结果:
    14
    17
    23
    25
    30

    根据上述结果可以看出TreeSet集合是自然排序和去重的,为什么会达到这样的效果呢?

    TreeSet集合的无参构造就是属于自然排序

    TreeSet<Integer> set=new TreeSet<Integer>();

    这是因为TreeSet集合依赖于TreeMap的红黑树结构实现的,下面让我们根据上述例题去看看红黑树结构的理解:

    set.add(17);

    set.add(25);

    set.add(23);

    set.add(14);

    set.add(17);

    set.add(30);

    17先进行存储,所以将17作为根节点,与后面的元素进行比较,25进来后与17相比,比17大,所以成为17的右孩子,放在17的右边,23进来比17大所以要放在17的右边,但是和25比较比他小,所以放在25的左边,接下来1417小放在17的左边,17进来与17的值一样不理睬,继续下个30,比17大比25大,放在右边25 的右边,绘成图就是二叉图方式,结构一定是自平衡的

    使用TreeSet进行自定义函数的排序,对年龄由小到大进行排序

    package com.TreeSetDome;
     
    public class Student implements Comparable<Student>{
     
    private String name;
    private int age;
    
    public Student() {
    super();
    }
    
    public Student(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 int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
     
    //因为上面Student类实现了comparable接口,所以必须重写comparaTo方法才能达到排序的效果
    @Override
    public int compareTo(Student s) {
    // return 0;
    /**
     * 因为这是我们自定义的类,系统并没有告诉我们如何进行排序
     * 所以需要我们自己手动进行排序
     * 需求:按年龄由小到大进行排序
     */
    //年龄进行排序,由小到大
    int num=this.age-s.age;
    //当年龄大小相等时,比较名字
    int num2=num==0?this.name.compareTo(s.getName()):num;
    return num2;
    }
    
    }

     

    package com.TreeSetDome;
     
    import java.util.TreeSet;
     
    public class StudentDome {
     
    public static void main(String[] args) {
    //创建TreeSet集合对象
    TreeSet<Student> set=new TreeSet<Student>();
    //创建学生对象,这里的学生姓名不要写成汉字,因为每个汉字的字节大小不一样
    Student s1=new Student("dilireba",27);
    Student s2=new Student("gaowen",25);
    Student s3=new Student("zhaoxingxing",24);
    Student s4=new Student("wuxuanyi",23);
    Student s5=new Student("dilireba",27);
    set.add(s1);
    set.add(s2);
    set.add(s3);
    set.add(s4);
    set.add(s5);
    //增强for循环
    for(Student st:set) {
    System.out.println(st.getName()+"---"+st.getAge());
    }
    }
    }
    运行结果:
    wuxuanyi---23
    zhaoxingxing---24
    gaowen---25
    dilireba---27

    由上例可以看出我们在学生类上实线了comparable接口,并且在学生类中重写了comparaTo方法,当我们没有进行以上的这些操作时,运行时就会出现这样的错误,

    Exception in thread "main" java.lang.ClassCastException: com.TreeSetDome.Student cannot be cast to java.lang.Comparable

    因为没有实现comparable接口,所以会出现以上的这个异常,但是为什么在前面添加数字的时候并不需要实现comparable接口呢?这是添加数字时我们确定了类型为Integer类型,它本身就已经实现了comparable接口,不需要我们再去添加,具体可以去API中观看,所以今后在使用TreeSet创建自定义类排序的时候,一定要自己去实现comparable接口,和重写comparaTo方法

    上述中我们重写的ComparaTo方法是按照年龄来排序的,接下来让我们按照姓名的长度以及年龄的大小来排序:

    @Override
    public int compareTo (Student s) {
    /**
     * 因为这是我们自定义的类,系统并没有告诉我们如何进行排序
     * 所以需要我们自己手动进行排序
     * 需求:按姓名的长度来排序,然后再以年龄的大小来排序
     */
    //按姓名的长短来排序,由小到大排序
    int num=this.getName().length()-s.getName().length();
    //再去比较的姓名的内容是否一致
    int num2=num==0?this.getName().compareTo(s.getName()):num;
    //名字一致,有时候并不是同一个人 还得再去比较年龄的大小
    int  num3=num2==0?this.age-s.age:num2;
    return num3;
    这是重写的comparaTo方法,我新添加了一个学生变量Student s6=new Student("dilireba",25);
     
    运行结果:
    gaowen---25
    dilireba---25
    dilireba---27
    wuxuanyi---23
    zhaoxingxing---24

    上面我们介绍了自然排序法,自然排序法主要就是运用TreeSet的无参构造,通过实现comparable接口中的comparaTo方法去进行自然排序,接下来让我们看看比较器排序,看看二者的不同

    package com.TreeSet;
     
    public class Student {
     
    private String name;
    private int age;
    public Student() {
    super();
    }
    
    public Student(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 int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    
    }

     

     

    package com.TreeSet;
     
    import java.util.Comparator;
    import java.util.NavigableMap;
     
    public class ComparatorDome implements Comparator<Student>{
     
    @Override
    /**
     * 因为测试类中TreeSet集合的引用参数是接口,所以需要创建这个子实现类去实现这个接口
     * 这里的s1就相当于自然排序中的this,s2相当于s
     * 先按名字的长度,当长度一致时,再按年龄的大小进行排序
     */
    public int compare(Student s1, Student s2) {
    //判断姓名长度的大小
    int num=s1.getName().length()-s2.getName().length();
    //长度一致时,比较内容
    int num2=num==0?s1.getName().compareTo(s2.getName()):num;
    //内容一致时,比较年龄的大小
    int num3=num2==0?(s1.getAge()-s2.getAge()):num2;
    return num3;
    }
     
    }

     

     

    package com.TreeSet;
     
    import java.util.TreeSet;
     
    public class StudentDome {
     
     
    public static void main(String[] args) {
    //创建TreeSet集合对象,运用比较器排序
    //Comparator是一个接口,所以我们得创建一个子实现类去实现它
    TreeSet<Student> set=new TreeSet<Student>(new ComparatorDome());
    //创建学生对象
    Student s1=new Student("dilireba",27);
    Student s2=new Student("gaowen",25);
    Student s3=new Student("zhaoxingxing",24);
    Student s4=new Student("wuxuanyi",23);
    Student s5=new Student("dilireba",25);
    Student s6=new Student("dilireba",25);
    //将学生对象添加到集合中
    set.add(s1);
    set.add(s2);
    set.add(s3);
    set.add(s4);
    set.add(s5);
    set.add(s6);
    //增强for循环遍历
    for(Student s:set) {
    System.out.println(s.getName()+"---"+s.getAge());
    }
    }
    }
    运行结果:
    gaowen---25
    dilireba---25
    dilireba---27
    wuxuanyi---23
    zhaoxingxing---24

    除了创建子实现类去实现Comparator接口,我们还可以在测试类中通过匿名内部类的方式去测试,就不用单独去创建一个子实现类了

    在这里学生类我就不写了,上面有,直接写测试类中的匿名内部类了

    package com.TreeSet;
     
    import java.util.Comparator;
    import java.util.TreeSet;
     
    public class StudentDome {
     
     
    public static void main(String[] args) {
    //创建TreeSet集合对象,运用比较器排序
    //Comparator是一个接口,所以我们得创建一个子实现类去实现它
    //匿名内部类的使用
    TreeSet<Student> set=new TreeSet<Student>(new Comparator<Student>() {
     
    @Override
    public int compare(Student s1, Student s2) {
    //判断姓名长度的大小
    int num=s1.getName().length()-s2.getName().length();
    //长度一致时,比较内容
    int num2=num==0?s1.getName().compareTo(s2.getName()):num;
    //内容一致时,比较年龄的大小
    int num3=num2==0?(s1.getAge()-s2.getAge()):num2;
    return num3;
    }
    
    });
    //创建学生对象
    Student s1=new Student("dilireba",27);
    Student s2=new Student("gaowen",25);
    Student s3=new Student("zhaoxingxing",24);
    Student s4=new Student("wuxuanyi",23);
    Student s5=new Student("dilireba",25);
    Student s6=new Student("dilireba",25);
    //将学生对象添加到集合中
    set.add(s1);
    set.add(s2);
    set.add(s3);
    set.add(s4);
    set.add(s5);
    set.add(s6);
    //增强for循环遍历
    for(Student s:set) {
    System.out.println(s.getName()+"---"+s.getAge());
    }
    }
    }
    运行结果:
    gaowen---25
    dilireba---25
    dilireba---27
    wuxuanyi---23
    zhaoxingxing---24

    展开全文
  • 而是指执行这些排序算法时,比较两个对象“大小”的比较操作。我们很容易理解整型的 i>j 这样的比较方式,但当我们对多个对象进行排序时,如何比较两个对象的“大小”呢?这样的比较 stu1 > stu2 显然是不可能通过...

    IT程序员开发必备-各类资源下载清单,史上最全IT资源,个人收藏总结!



    这里所说到的Java中的排序并不是指插入排序、希尔排序、归并排序等具体的排序算法。而是指执行这些排序算法时,比较两个对象“大小”的比较操作。我们很容易理解整型的 i>j 这样的比较方式,但当我们对多个对象进行排序时,如何比较两个对象的“大小”呢?这样的比较 stu1 > stu2 显然是不可能通过编译的。为了解决如何比较两个对象大小的问题,JDK提供了两个接口 java.lang.Comparable 和 java.util.Comparator 。

    一、自然排序:java.lang.Comparable
      Comparable 接口中只提供了一个方法: compareTo(Object obj) ,该方法的返回值是 int 。如果返回值为正数,则表示当前对象(调用该方法的对象)比 obj 对象“大”;反之“小”;如果为零的话,则表示两对象相等。下面是一个实现了 Comparable 接口的 Student 类:
    1. public class Student implements Comparable {  
    2.   
    3.     private int id;  
    4.       
    5.     private String name;  
    6.   
    7.     public Student() {  
    8.         super();  
    9.     }  
    10.   
    11.     @Override  
    12.     public int compareTo(Object obj) {  
    13.         if (obj instanceof Student) {  
    14.             Student stu = (Student) obj;  
    15.             return id - stu.id;  
    16.         }  
    17.         return 0;  
    18.     }  
    19.   
    20.     @Override  
    21.     public String toString() {  
    22.         return "<" + id + ", " + name + ">";  
    23.     }  
    24. }  

     

      Student 实现了自然排序接口 Comparable ,那么我们是怎么利用这个接口对一组 Student 对象进行排序的呢?我们在学习数组的时候,使用了一个类来给整型数组排序: java.util.Arrays 。我们使用 Arrays 的 sort 方法来给整型数组排序。翻翻 API 文档就会发现, Arrays 里给出了 sort 方法很多重载形式,其中就包括 sort(Object[] obj) ,也就是说 Arryas 也能对对象数组进行排序,排序过程中比较两个对象“大小”时使用的就是 Comparable 接口的 compareTo 方法。

    1. public class CompareTest {  
    2.   
    3.     public static void main(String[] args) {  
    4.         Student stu1 = new Student(1"Little");  
    5.         Student stu2 = new Student(2"Cyntin");  
    6.         Student stu3 = new Student(3"Tony");  
    7.         Student stu4 = new Student(4"Gemini");  
    8.           
    9.         Student[] stus = new Student[4];  
    10.         stus[0] = stu1;  
    11.         stus[1] = stu4;  
    12.         stus[2] = stu3;  
    13.         stus[3] = stu2;  
    14.         System.out.println(“Array: ” + Arrays.toString(stus));   
    15.         Arrays.sort(stus);   
    16.         System.out.println(“Sort:  ” + Arrays.toString(stus));  
    17.     }  
    18. }  

     

     Student 数组里添加元素的顺序并不是按学号 id 来添加的。调用了 Arrays.sort(stus) 之后,对 Student 数组进行排序,不管 sort 是使用哪种排序算法来实现的,比较两个对象“大小”这个操作,它是肯定要做的。那么如何比较两个对象的“大小”? Student 实现的 Comparable 接口就发挥作用了。 sort 方法会将待比较的那个对象强制类型转换成 Comparable ,并调用 compareTo 方法,根据其返回值来判断这两个对象的“大小”。所以,在这个例子中排序后的原 Student 乱序数组就变成了按学号排序的 Student 数组。

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

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

      翻翻 API 会发现, Arrays.sort 还有种重载形式:sort(T[] a, Comparator<? super T> c) ,这个方法参数的写法用到了泛型,我们还没讲到。我们可以把它理解成这样的形式: sort(Object[] a, Comparator c) ,这个方法的意思是按照比较器 c 给出的比较排序算法,对 Object 数组进行排序。Comparator 接口中定义了两个方法: compare(Object o1, Object o2) 和 equals 方法,由于 equals 方法所有对象都有的方法,因此当我们实现 Comparator 接口时,我们只需重写 compare 方法,而不需重写 equals 方法。Comparator 接口中对重写 equals 方法的描述是:“注意,不重写 Object.equals(Object) 方法总是安全的。然而,在某些情况下,重写此方法可以允许程序确定两个不同的 Comparator 是否强行实施了相同的排序,从而提高性能。”。我们只需知道第一句话就OK了,也就是说,可以不用去想应该怎么实现 equals 方法,因为即使我们不显示实现 equals 方法,而是使用Object类的 equals 方法,代码依然是安全的。而对于第二句话,究竟是怎么提高比较器性能的,我也不了解,所以就不说了。

      那么我们来写个代码,来用一用比较器排序。还是用 Student 类来做,只是没有实现 Comparable 接口。由于比较器的实现类只用显示实现一个方法,因此,我们可以不用专门写一个类来实现它,当我们需要用到比较器时,可以写个匿名内部类来实现 Comparator 。下面是我们的按姓名排序的方法:

    1. public void sortByName () {  
    2.     Student stu1 = new Student(1"Little");  
    3.     Student stu2 = new Student(2"Cyntin");  
    4.     Student stu3 = new Student(3"Tony");  
    5.     Student stu4 = new Student(4"Gemini");  
    6.       
    7.     Student[] stus = new Student[4];  
    8.     stus[0] = stu1;  
    9.     stus[1] = stu4;  
    10.     stus[2] = stu3;  
    11.     stus[3] = stu2;  
    12.     System.out.println("Array: " + Arrays.toString(stus));  
    13.   
    14.     Arrays.sort(stus, new Comparator() {  
    15.   
    16.         @Override  
    17.         public int compare(Object o1, Object o2) {  
    18.             if (o1 instanceof Student && o2 instanceof Student) {  
    19.                 Student s1 = (Student) o1;  
    20.                 Student s2 = (Student) o2;  
    21.                 //return s1.getId() - s2.getId(); // 按Id排  
    22.                 return s1.getName().compareTo(s2.getName()); // 按姓名排  
    23.             }  
    24.             return 0;  
    25.         }  
    26.           
    27.     });  
    28.       
    29.     System.out.println("Sorted: " + Arrays.toString(stus));  
    30. }  

      当我们需要对Student按学号排序时,只需修改我们的排序方法中实现Comparator的内部类中的代码,而不用修改 Student 类。

      P.S. 当然,你也可以用 Student 类实现 Comparator 接口,这样Student就是(is a)比较器了(Comparator)。当需要使用这种排序的时候,将 Student 看作 Comparator 来使用就可以了,可以将 Student 作为参数传入 sort 方法,因为 Student is a Comparator 。但这样的代码不是个优秀的代码,因为我们之所以使用比较器(Comparator),其中有个重要的原因就是,这样可以把比较算法和具体类分离,降低类之间的耦合。

      上一篇博客里说到了,TreeSet对这两种比较方式都提供了支持,分别对应着TreeSet的两个构造方法:
        1、TreeSet():根据TreeSet中元素实现的 Comparable 接口的 compareTo 方法比较排序
        2、TreeSet(Comparator comparator):根据给定的 comparator 比较器,对 TreeSet 中的元素比较排序
      当向 TreeSet 中添加元素时,TreeSet 就会对元素进行排序。至于是用自然排序还是用比较器排序,就看你的 TreeSet 构造是怎么写的了。当然,添加第一个元素时不会进行任何比较, TreeSet 中都没有元素,和谁比去啊?

      下面,分别给出使用两种排序比较方式的 TreeSet 测试代码:

    1. /** 
    2.  * 使用自然排序 
    3.  * Student必须实现Comparable接口,否则会抛出ClassCastException 
    4.  */  
    5. public void testSortedSet3() {  
    6.     Student stu1 = new Student(1"Little");  
    7.     Student stu2 = new Student(2"Cyntin");  
    8.     Student stu3 = new Student(3"Tony");  
    9.     Student stu4 = new Student(4"Gemini");  
    10.   
    11.     SortedSet set = new TreeSet();  
    12.     set.add(stu1);  
    13.     set.add(stu3); // 若Student没有实现Comparable接口,抛出ClassCastException  
    14.     set.add(stu4);  
    15.     set.add(stu2);  
    16.     set.add(stu4);  
    17.     set.add(new Student(12"Little"));  
    18.   
    19.     System.out.println(set);  
    20. }  
    1. /** 
    2.  * 使用比较器排序 
    3.  * Student可以只是个简单的Java类,不用实现Comparable接口 
    4.  */  
    5. public void testSortedSet3() {  
    6.     Student stu1 = new Student(1"Little");  
    7.     Student stu2 = new Student(2"Cyntin");  
    8.     Student stu3 = new Student(3"Tony");  
    9.     Student stu4 = new Student(4"Gemini");  
    10.   
    11.     SortedSet set = new TreeSet(new Comparator() {  
    12.   
    13.         @Override  
    14.         public int compare(Object o1, Object o2) {  
    15.             if (o1 instanceof Student  
    16.                     && o2 instanceof Student) {  
    17.                 Student s1 = (Student) o1;  
    18.                 Student s2 = (Student) o2;  
    19.                 return s1.getName().compareTo(s2.getName());  
    20.             }  
    21.             return 0;  
    22.         }  
    23.           
    24.     });  
    25.   
    26.     set.add(stu1);  
    27.     set.add(stu3);  
    28.     set.add(stu4);  
    29.     set.add(stu2);  
    30.     set.add(stu4);  
    31.     set.add(new Student(12"Little"));  
    32.   
    33.     System.out.println(set);  
    34. }  

      另外,介绍个工具类,java.util.Collections。注意,这不是Collection接口。Collections很像Arrays类。Arrays提供了一系列用于对数组操作的静态方法,查找排序等等。Collections也提供了一系列这样的方法,只是它是用于处理集合的,虽然Collections类和Collection接口很像,但是不要被Collections的名字给欺骗了,它不是只能处理Collection接口以及子接口的实现类,同样也可以处理Map接口的实现类。


    展开全文
  • 比较器(ComparableComparator)、自然排序、定制排序

    千次阅读 多人点赞 2019-11-07 19:53:53
    比如Integer,double等基本类型数据,Java可以对他们进行比较排序,但是在 Java 中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题 。这篇博客对比较器进行了详细的说明并配有完整的代码实现。
  • java中ComparableComparator的用法区别 Comparable自然排序 Comparator比较器排序 一、概述 ComparableComparator在java中都是用于来比较数据大小。实现Comparable接口需要重写compareTo方法,实现...
  • * 对字符串进行自然排序和长度排序 */ public class CollectionsDemo { public static void main(String[] args) { ArrayList<String> al = new ArrayList(); al.add("fa"); al.add("gaa"); al....
  • 在涉及到数组, 集合等这些地方经常会需要用到排序算法, 在Java中的Collections类中有sort方法, 除了需要传入一个Comparator比较器, 或者需要排序的类实现了Comparable接口; 完整的测试代码附在最后面~ 1.使用lambda...
  • 【TreeSet】自然排序与比较器排序

    千次阅读 2016-09-01 20:21:22
    使用TreeSet比较器排序法时不需要实现Comparable接口,只在新建TreeSet时使用匿名内部类重写compareTo方法即可。当对象类为Java内部类或其他没有修改权限的类时可以使用此方法。效果与自然排序相同。在重写compareTo...
  • List集合排序、自定义比较器排序

    千次阅读 2019-08-20 17:25:12
    List集合排序 ...将list转成了数组对象后,调用了Array的sort方法,将数组排序,再用list的迭代(注意不是collection迭代)一个个得赋值回去,就使得传入的list变成了一个有序的list 由于s...
  • java排序重写比较器

    千次阅读 2019-04-04 14:55:22
    有时候我们用arrays.sort或者collections.sort的时候我们需要重写比较器来按照我们想要的比较方式对某些元素进行比较或者排序,那么怎么重写比较器呢?下面给出方法 我们先定义一个Interval类: public class ...
  • 【附章3Java比较器】的两个排序你知道吗?

    千次阅读 多人点赞 2022-01-17 14:19:02
    【Java比较器:两大排序自然排序、定制排序
  • List集合数据排序使用比较器

    千次阅读 2017-07-19 11:23:47
    开发中有时候需要自己封装分页排序时,List如何对某一属性排序呢,分享一个小实例,大家共勉,希望能对大家有用,请多多指教。 1.Student的Bean如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 ...
  • TreeMap的排序比较器问题

    万次阅读 2016-07-17 23:03:52
    本文介绍了Map的按值排序以及由此引出的比较器等的问题,深入探讨了Comparator及Comparable两个比较器的不同之处,希望给他人以帮助。
  • TreeSet的两种排序方式:自然排序和定制排序 TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。TreeSet有两种排序方法:自然排序和定制排序。默认采用自然排序。 1. 自然排序 要求自定义类...
  • TreeSet的自然排序和定制排序

    千次阅读 2017-07-31 07:15:49
    (该方法不能自动生成)自然排序(Comparable) TreeSet拥有的集合元素的compareTo()方法来比较元素的大小关系,然后将集合元素按照升序排列。 int compareTo(T o) 将此对象与指定的对象进行比较,以返
  • JAVA比较器排序及对比自然排序

    万次阅读 2016-07-20 11:39:22
     上篇博客(自然排序)我提到了之所以提供比较器排序接口,是因为有时需要对同一对象进行多种不同方式的排序,这点自然排序 Comparable 不能实现。另外, Comparator 接口的一个好处是将比较排序算法具体的实体类...
  • 使用比较器实现list排序

    千次阅读 2016-12-21 12:07:18
    Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等...此列表内的所有元素都必须是使用指定比较器可相互比较的 1.使用java提供的默认排序方法 主
  • 说到比较器我们第一时间会想到equals,但是equals是用来比较是否相等的,Comparator或者Comparable是用来比较顺序的(也就是排序)。比较器的概念确定两个对象之间的大小关系及排列顺序称为比较,能实现这个比较功能...
  • C#排序函数自定义比较器

    千次阅读 2015-11-06 12:18:28
    C#排序函数自定义比较器 例子
  • 面试题 - 二输入比较器实现排序算法 @(数字集成电路基础) 1. 问题描述 给定8个数,以及若干二输入的比较器(可以将两个输入排序)。要求在单周期内实现8个数的排序,并使用最少的比较器个数。(乐鑫) (距离面试...
  • 在C++中可以使用STL库中的实现完成排序和搜索,我们只需要定义比较器就可以支持任意类型的任务。 api std::stable_sort: 元素相等时保持原有顺序,内部实现是归并排序。 std::sort:元素相等时不保证原有顺序,内部...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 456,239
精华内容 182,495
关键字:

自然排序和比较器排序