zoukankan      html  css  js  c++  java
  • TreeSet ------自然排序与定制排序(比较器)

    前言:TreeSet集合是Set集合的一个子实现类,它是基于TreeMap中的NavigableSet接口实现的,TreeSet集合是默认通过自然排序将集合中的元素进行排序

      TreeSet有两种排序方式:

      1)自然排序

      2)比较器排序(定制排序)

       当定制排序和自然排序同时存在时,最终的排序结果是按照  定制排序  来的。

    面试题:Comparable 和Comparator的区别:

    ① Comparable 自然排序 ,实体类实现Comparable接口,可以去重写compareTo()方法,解决实际排序问题。  把元素放到TreeSet里面去,就会自动的调用CompareTo方法; 但是这个Comparable并不是专为TreeSet设计的;只是说TreeSet顺便利用而已; 就像haashCodeequals 也一样,不是说专门为HashSet设计一样;只是你顺便利用而已;

    ② Compartor第三方的比较器接口,也不是专门为TreeSet设计。 用法:设计一个比较器. 创建一个类,实现这个接口,覆写compare()方法,解决不同问题的需求。

     

    1. 自然排序:

      在TreeSet中默认要求里面的元素进行自然排序,强制要求里面的所有元素必须按照Comparable中的compareTo方法进行比较。

      如果容器里面的对象(比如:new Student(参数)对象)不具备compareTo方法此时就会抛出异常报错(ClassCastException),所以必须要让容器中的元素实现Comparable接口,这样它才具备compareTo方法。

        1.TreeSet实例在调用add方法时会调用容器对象的compareTo方法对元素进行比较

        2.TreeSet实例中对象必须是实现了Comparable接口

     

    例如:比较Student学生类,应该从哪些方法进行比较?

    一般从字段的方面进行比较;比如按照年龄比较;当年龄相等返回0,大于返回1,小于返回-1

    姓名是字符串,怎样比较大小,查看api的时候,String已经实现了Comparable接口,String 类里面已经肯定覆写Comparable方法,那是按照String的规则进行比较。

    可以直接不管具体内 部是怎样比较,直接调用String类里面比较方法就可以.

     

    package TreeSet;
    
    public class Student implements Comparable {
        private int age;  
        private String name;
        public Student(){}
        public Student(int age,String name){
            this.age = age;
            this.name = name;
        }
        
        @Override
        public int compareTo(Object obj) {
    //比如按照年龄比较;当年龄相等返回0,大于返回1,小于返回-1
            Student stu = (Student)obj;
            if(this.age > stu.age){
                return 1;
            }else if(this.age<stu.age){
                return -1;
            }else{
                return this.name.compareTo(stu.name);
            }
        }  
        
        @Override  
        public String toString() {  
            return "<" + age + ", " + name + ">";  
        }  
    
    }

     

    public class TestStudent {
        public static void main(String[] args) {
            
            TreeSet set = new TreeSet();
            set.add(new Student(20, "zs"));
            set.add(new Student(21, "zs"));
            set.add(new Student(22, "ww"));
            set.add(new Student(23, "zl"));
            System.out.println(set);
        }
    }
    //结果:[<20, zs>, <21, zs>, <22, ww>, <23, zl>]

     2)比较器排序     创建TreeSet时,向其中传入已经重写Comparator中方法的对象

    下面通过一个案例了解定制排序:

    题目:  某班30个学生的学号为20070301-20070330,全部选修了Java程序设计课程,给出所有同学的成绩(可用随机数产生,范围60-100),
           请编写程序将本班各位同学的成绩按照从低到高排序打印输出。
           要求:1.分别用List、Set来实现,打印的信息包括学号、姓名和成绩。
            2.用迭代器遍历

    public class Student {
        private String name;
        private int id;
        private int score;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public int getScore() {
            return score;
        }
        public void setScore(int score) {
            this.score = score;
        }
        public Student(){}
        public Student(String name, int id, int score) {
            super();
            this.name = name;
            this.id = id;
            this.score = score;
        }
        @Override
        public String toString() {
            return "学生 [姓名=" + name + ", 学号=" + id + ", 成绩=" + score + "]";
        }
    import java.util.Comparator;
    
    public class myComparator implements Comparator{
    
        @Override
        public int compare(Object o1, Object o2) {
            Student s1 = (Student)o1;
            Student s2 = (Student)o2;
            if(s1.getScore()>s2.getScore()){
                return 1;
            }else if(s1.getScore()<s2.getScore()){
                return -1;
            }else{
                return s1.getName().compareTo(s2.getName());
            }
        }
    
    }
    package 学生成绩排序题目;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.TreeSet;
    
    public class Test {
        public static void main(String[] args) {
    //使用list集合+定制排序+迭代器遍历(注意list.sort(), list不支持自然排序)
            List list = new ArrayList();
            for(int i =20070301;i<=20070330;i++){
                Student s = new Student("代号$"+(i-20070300),i,(int)(Math.random()*41+60));
                list.add(s);
            }
    /*
    //这里涉及list集合排序的两种方法
            list.sort(new myComparator());
            
    //这里介绍Collections工具类的sort()方法:
      //参数不同:       1. void sort(List list),按自然排序的升序排序
    //                2. void sort(List list, Comparator c);定制排序,由Comparator控制排序逻辑
    
    //        1. Collections.sort(list);  
            //这里由于Student类中没有实现自然排序,所以直接调用会报类型转换异常 ClassCastException
            
    //        2. Collections.sort(list,new myComparator()); //可以正常排序
            
            
            Iterator it = list.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
    */
    
    //使用TreeSet集合+定制排序+迭代器遍历,并统计个数(也可以使用treeSet的自然排序)
            TreeSet set = new TreeSet(new myComparator());
            for(int i =20070301;i<=20070330;i++){
                Student s = new Student("代号$"+(i-20070300),i,(int)(Math.random()*41+60));
                set.add(s);
            }
            
            Iterator it = set.iterator();
            int count  = 0;
            while(it.hasNext()){
                count++;
                System.out.println(count);
                System.out.println(it.next());
            }
        }
    
    }
    结果:
    1
    学生 [姓名=代号$10, 学号=20070310, 成绩=60]
    2
    学生 [姓名=代号$12, 学号=20070312, 成绩=60]
    3
    学生 [姓名=代号$26, 学号=20070326, 成绩=60]
    4
    学生 [姓名=代号$1, 学号=20070301, 成绩=61]
    5
    学生 [姓名=代号$28, 学号=20070328, 成绩=65]
    6
    学生 [姓名=代号$21, 学号=20070321, 成绩=69]
    7
    学生 [姓名=代号$11, 学号=20070311, 成绩=71]
    8
    学生 [姓名=代号$24, 学号=20070324, 成绩=71]
    9
    学生 [姓名=代号$16, 学号=20070316, 成绩=72]
    10
    学生 [姓名=代号$5, 学号=20070305, 成绩=72]
    11
    学生 [姓名=代号$9, 学号=20070309, 成绩=73]
    12
    学生 [姓名=代号$2, 学号=20070302, 成绩=74]
    13
    学生 [姓名=代号$3, 学号=20070303, 成绩=74]
    14
    学生 [姓名=代号$20, 学号=20070320, 成绩=76]
    15
    学生 [姓名=代号$6, 学号=20070306, 成绩=78]
    16
    学生 [姓名=代号$14, 学号=20070314, 成绩=79]
    17
    学生 [姓名=代号$29, 学号=20070329, 成绩=79]
    18
    学生 [姓名=代号$7, 学号=20070307, 成绩=79]
    19
    学生 [姓名=代号$18, 学号=20070318, 成绩=80]
    20
    学生 [姓名=代号$17, 学号=20070317, 成绩=83]
    21
    学生 [姓名=代号$25, 学号=20070325, 成绩=87]
    22
    学生 [姓名=代号$13, 学号=20070313, 成绩=88]
    23
    学生 [姓名=代号$15, 学号=20070315, 成绩=89]
    24
    学生 [姓名=代号$30, 学号=20070330, 成绩=89]
    25
    学生 [姓名=代号$8, 学号=20070308, 成绩=90]
    26
    学生 [姓名=代号$23, 学号=20070323, 成绩=92]
    27
    学生 [姓名=代号$19, 学号=20070319, 成绩=93]
    28
    学生 [姓名=代号$27, 学号=20070327, 成绩=93]
    29
    学生 [姓名=代号$4, 学号=20070304, 成绩=93]
    30
    学生 [姓名=代号$22, 学号=20070322, 成绩=98]

     

  • 相关阅读:
    android 运行时异常捕获
    汇编32位寄存器和地址编号的五种书写形式
    各种进制的乘法表,八进制的加法,和数字的源码你,反码,和补码
    第一个c程序和vs2017 在打开MFC rc文件时找不到rcdll.dl
    asdfasdf
    php如何判断一个字符串是否包含另一个字符串
    php计算时间差/两个时间日期相隔的天数,时,分,秒.
    PHP服务器时间差8小时解决方案
    历年学生作品评论
    第一周例行报告
  • 原文地址:https://www.cnblogs.com/gshao/p/10129139.html
Copyright © 2011-2022 走看看