• TreeSet的两种排序方式,含Comparable、Comparator


    1.排序的引入

    由于TreeSet可以实现对元素按照某种规则进行排序,例如下面的例子

     1 public class TreeSetDemo {
     2     public static void main(String[] args) {
     3         // 创建集合对象
     4         // 自然顺序进行排序
     5         TreeSet<Integer> ts = new TreeSet<Integer>();
     6  
     7         // 创建元素并添加
     8         // 20,18,23,22,17,24,19,18,24
     9         ts.add(20);
    10         ts.add(18);
    11         ts.add(23);
    12         ts.add(22);
    13         ts.add(17);
    14         ts.add(24);
    15         ts.add(19);
    16         ts.add(18);
    17         ts.add(24);
    18  
    19         // 遍历
    20         for (Integer i : ts) {
    21             System.out.println(i);
    22         }
    23     }
    24 }

     运行结果为:

    但是对自定义对象呢?

     1 public class TreeSetDemo02 {
     2     public static void main(String[] args) {
     3         TreeSet<Student> ts=new TreeSet<Student>();        
     4         //创建元素对象
     5         Student s1=new Student("zhangsan",20);
     6         Student s2=new Student("lis",22);
     7         Student s3=new Student("wangwu",24);
     8         Student s4=new Student("chenliu",26);
     9         Student s5=new Student("zhangsan",22);
    10         Student s6=new Student("qianqi",24);
    11         
    12         //将元素对象添加到集合对象中
    13         ts.add(s1);
    14         ts.add(s2);
    15         ts.add(s3);
    16         ts.add(s4);
    17         ts.add(s5);
    18         ts.add(s6);
    19         
    20         //遍历
    21         for(Student s:ts){
    22             System.out.println(s.getName()+"-----------"+s.getAge());
    23         }
    24     }
    25 }



     Student类:

     1 public class Student {
     2     private String name;
     3     private int age;
     4     
     5     public Student() {
     6         super();
     7         // TODO Auto-generated constructor stub
     8     }    
     9  
    10     public Student(String name, int age) {
    11         super();
    12         this.name = name;
    13         this.age = age;
    14     }
    15  
    16     public String getName() {
    17         return name;
    18     }
    19  
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23  
    24     public int getAge() {
    25         return age;
    26     }
    27  
    28     public void setAge(int age) {
    29         this.age = age;
    30     }
    31 }

    运行结果:

    原因分析:
    由于不知道该安照那一中排序方式排序,所以会报错。
     
    解决方法:
       1.自然排序
    2.比较器排序

    2.自然排序

    自然排序要进行一下操作:
     
    1.Student类中实现  Comparable<T>接口
    2.重写Comparable接口中的Compareto方法
    int compareTo(T o)
              比较此对象与指定对象的顺序。

    故Student类为:特别注意在重写Compareto方法时,注意排序 

     1 package xfcy_04;
     2 /**
     3  * Student类
     4  * @author 晓风残月
     5  *
     6  */
     7 public class Student implements Comparable<Student> {
     8     private String name;
     9     private int age;
    10     
    11     public Student() {
    12         super();
    13         // TODO Auto-generated constructor stub
    14     }    
    15  
    16     public Student(String name, int age) {
    17         super();
    18         this.name = name;
    19         this.age = age;
    20     }
    21  
    22     public String getName() {
    23         return name;
    24     }
    25  
    26     public void setName(String name) {
    27         this.name = name;
    28     }
    29  
    30     public int getAge() {
    31         return age;
    32     }
    33  
    34     public void setAge(int age) {
    35         this.age = age;
    36     }
    37  
    38     @Override
    39     public int compareTo(Student s) {
    40         //return -1; //-1表示放在红黑树的左边,即逆序输出
    41         //return 1;  //1表示放在红黑树的右边,即顺序输出
    42         //return o;  //表示元素相同,仅存放第一个元素
    43         //主要条件 姓名的长度,如果姓名长度小的就放在左子树,否则放在右子树
    44         int num=this.name.length()-s.name.length();  
    45         //姓名的长度相同,不代表内容相同,如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。
    46         //如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。
    47         //如果这两个字符串相等,则结果为 0
    48         int num1=num==0?this.name.compareTo(s.name):num;
    49         //姓名的长度和内容相同,不代表年龄相同,所以还要判断年龄
    50         int num2=num1==0?this.age-s.age:num1;
    51         return num2;
    52     }
    53     
    54 }

    而主类中为:

     1 package xfcy_04;
     2  
     3 import java.util.TreeSet;
     4  
     5 /*
     6 * TreeSet存储自定义对象并保证排序和唯一。
     7  * 
     8  * 需求:请按照姓名的长度排序
     9  */
    10 public class TreeSetDemo02 {
    11     public static void main(String[] args) {
    12         //创建集合对象        
    13         TreeSet<Student> ts=new TreeSet<Student>();
    14  
    15         
    16         //创建元素对象
    17         Student s1=new Student("zhangsan",20);
    18         Student s2=new Student("lis",22);
    19         Student s3=new Student("wangwu",24);
    20         Student s4=new Student("chenliu",26);
    21         Student s5=new Student("zhangsan",22);
    22         Student s6=new Student("qianqi",24);
    23         
    24         //将元素对象添加到集合对象中
    25         ts.add(s1);
    26         ts.add(s2);
    27         ts.add(s3);
    28         ts.add(s4);
    29         ts.add(s5);
    30         ts.add(s6);
    31         
    32         //遍历
    33         for(Student s:ts){
    34             System.out.println(s.getName()+"-----------"+s.getAge());
    35         }
    36     }
    37 }

    运行结果:

    3、比较器排序

    比较器排序步骤:
    1.单独创建一个比较类,这里以MyComparator为例,并且要让其继承Comparator<T>接口
    2.重写Comparator接口中的Compare方法
     
    3.在主类中使用下面的 构造方法
     
    TreeSet(Comparator<? superE> comparator) 
              构造一个新的空 TreeSet,它根据指定比较器进行排序。
     
     
    主类:
     1 package xfcy_04;
     2  
     3 import java.util.TreeSet;
     4  
     5 /*
     6 * TreeSet存储自定义对象并保证排序和唯一。
     7  * 
     8  * 需求:请按照姓名的长度排序
     9  */
    10 public class TreeSetDemo02 {
    11     public static void main(String[] args) {
    12         //创建集合对象
    13         //TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。
    14         TreeSet<Student> ts=new TreeSet<Student>(new MyComparator());
    15  
    16         //创建元素对象
    17         Student s1=new Student("zhangsan",20);
    18         Student s2=new Student("lis",22);
    19         Student s3=new Student("wangwu",24);
    20         Student s4=new Student("chenliu",26);
    21         Student s5=new Student("zhangsan",22);
    22         Student s6=new Student("qianqi",24);
    23         
    24         //将元素对象添加到集合对象中
    25         ts.add(s1);
    26         ts.add(s2);
    27         ts.add(s3);
    28         ts.add(s4);
    29         ts.add(s5);
    30         ts.add(s6);
    31         
    32         //遍历
    33         for(Student s:ts){
    34             System.out.println(s.getName()+"-----------"+s.getAge());
    35         }
    36     }
    37 }

    MyComparator类:

     1 package xfcy_04;
     2  
     3 import java.util.Comparator;
     4  
     5 public class MyComparator implements Comparator<Student>{
     6  
     7     @Override
     8     public int compare(Student s1,Student s2) {
     9         // 姓名长度
    10         int num = s1.getName().length() - s2.getName().length();
    11         // 姓名内容
    12         int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
    13         // 年龄
    14         int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
    15         return num3;
    16     }
    17     
    18     
    19     
    20     
    21 }

    学生类(不需要继承Comparetable接口)

     1 package xfcy_04;
     2 /**
     3  * Student类
     4  * @author 晓风残月
     5  *
     6  */
     7 public class Student{
     8     private String name;
     9     private int age;
    10     
    11     public Student() {
    12         super();
    13         // TODO Auto-generated constructor stub
    14     }    
    15  
    16     public Student(String name, int age) {
    17         super();
    18         this.name = name;
    19         this.age = age;
    20     }
    21  
    22     public String getName() {
    23         return name;
    24     }
    25  
    26     public void setName(String name) {
    27         this.name = name;
    28     }
    29  
    30     public int getAge() {
    31         return age;
    32     }
    33  
    34     public void setAge(int age) {
    35         this.age = age;
    36     }
    37     
    38 }

    运行结果:

    4.比较器修改(代码精简)

    由于单独创建一个类不是特别好,因而可以将MyComparetor的内容直接写到主类中

     1 public class TreeSetDemo {
     2         public static void main(String[] args) {
     3                 // 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
     4         // 而匿名内部类就可以实现这个东西
     5         TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
     6             @Override
     7             public int compare(Student s1, Student s2) {
     8                 // 姓名长度
     9                 int num = s1.getName().length() - s2.getName().length();
    10                 // 姓名内容
    11                 int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
    12                         : num;
    13                 // 年龄
    14                 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
    15                 return num3;
    16             }
    17         });
    18  
    19         // 创建元素
    20         Student s1 = new Student("linqingxia", 27);
    21         Student s2 = new Student("zhangguorong", 29);
    22         Student s3 = new Student("wanglihong", 23);
    23         Student s4 = new Student("linqingxia", 27);
    24         Student s5 = new Student("liushishi", 22);
    25         Student s6 = new Student("wuqilong", 40);
    26         Student s7 = new Student("fengqingy", 22);
    27         Student s8 = new Student("linqingxia", 29);
    28  
    29         // 添加元素
    30         ts.add(s1);
    31         ts.add(s2);
    32         ts.add(s3);
    33         ts.add(s4);
    34         ts.add(s5);
    35         ts.add(s6);
    36         ts.add(s7);
    37         ts.add(s8);
    38  
    39         // 遍历
    40         for (Student s : ts) {
    41             System.out.println(s.getName() + "---" + s.getAge());
    42         }
    43     }
    44 }
    运行结果也如同上面一样
     

    5.总结

    A:自然排序:要在自定义类中实现Comparerable<T>接口  ,并且重写compareTo方法
    B:比较器排序:在自定义类中实现Comparetor<t>接口,重写compare方法
  • 相关阅读:
    C#基础系列——一场风花雪月的邂逅:接口和抽象类
    C#进阶系列——动态Lamada(二:优化)
    C#进阶系列——动态Lamada
    JS组件系列——Bootstrap Table 表格行拖拽(二:多行拖拽)
    JS组件系列——Bootstrap Table 表格行拖拽
    C#进阶系列——DDD领域驱动设计初探(七):Web层的搭建
    C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入
    C#进阶系列——DDD领域驱动设计初探(六):领域服务
    C#进阶系列——DDD领域驱动设计初探(五):AutoMapper使用
    C#进阶系列——DDD领域驱动设计初探(四):WCF搭建
  • 原文地址:https://www.cnblogs.com/jiliunyongjin/p/9603246.html
Copyright © 2020-2023  润新知