TreeSet集合的自然排序与比较器排序、Comparable接口的compareTo()方法

【自然排序】

 1 package com.hxl;
 2 
 3 public class Student implements Comparable<Student> {
 4 
 5     private String name;
 6     private int age;
 7 
 8     public Student() {
 9         super();
10     }
11 
12     public Student(String name, int age) {
13         super();
14         this.name = name;
15         this.age = age;
16     }
17 
18     public String getName() {
19         return name;
20     }
21 
22     public void setName(String name) {
23         this.name = name;
24     }
25 
26     public int getAge() {
27         return age;
28     }
29 
30     public void setAge(int age) {
31         this.age = age;
32     }
33 
34     @Override
35     public int compareTo(Student s) {
36         // 先让两个对象的age属性做差比较,这个是主要排序条件
37         int num = this.age - s.age;
38         // 若age属性相同,再比较name属性(String类本身实现了Comparable接口)
39         // 即在主要排序条件相同的情况下,次要排序条件起作用
40         int flag = num == 0 ? this.name.compareTo(s.name) : num;
41         // 返回比较结果
42         return flag;
43     }
44 }
 1 package com.hxl;
 2 
 3 import java.util.TreeSet;
 4 
 5 public class Test {
 6     public static void main(String[] args) {
 7         //这里使用的无参构造实例化TreeSet集合,则默认启用的是自然排序
 8         TreeSet<Student> ts = new TreeSet<Student>();
 9         ts.add(new Student("cc", 11));
10         ts.add(new Student("ee", 11));
11         ts.add(new Student("cc", 22));
12         ts.add(new Student("aa", 22));
13         ts.add(new Student("bb", 11));
14 
15         for (Student s : ts) {
16             System.out.println(s.getName()+"_"+s.getAge());
17         }
18 
19         /*
20             为什么TreeSet集合中的元素既唯一又有序呢?
21             原因是它在存储元素的时候就是有序存储的(红黑树结构存储)
22             TreeSet的add()方法底层依赖的是Comparable的compareTo方法
23             这里就是说元素类本身要有自己的compareTo方法
24             所以元素类本身必须实现Comparable接口,重写compareTo方法
25             compareTo方法有个特点:它返回的是int型数据,结果有三类负数、0、正数
26             例如:(Java中一些常见的有比较意义的一些类都实现了Comparable接口,如Integer类)
27                 Integer a = new Integer(10);
28                 Integer b = new Integer(20);
29                 int num = a.compareTo(b);     //因为a小于b,所以num返回的是负数
30             而TreeSet的add()方法这样理解此返回值:
31             即返回负数则比根节点小,元素在此集合中唯一,元素存放根的左孩子
32             返回正数则比根节点大,元素在此集合中唯一,元素存放根的右孩子
33             返回0则表示,元素相同,在此集合中不唯一,故而丢掉不存放
34             由此可见,我们的重写的compareTo()方法决定了TreeSet集合中元素的去留和顺序!
35         */
36     }
37 }

【比较器排序(外部类实现)】

 1 package com.hxl;
 2 
 3 public class Student{
 4 
 5     private String name;
 6     private int age;
 7 
 8     public Student() {
 9         super();
10     }
11 
12     public Student(String name, int age) {
13         super();
14         this.name = name;
15         this.age = age;
16     }
17 
18     public String getName() {
19         return name;
20     }
21 
22     public void setName(String name) {
23         this.name = name;
24     }
25 
26     public int getAge() {
27         return age;
28     }
29 
30     public void setAge(int age) {
31         this.age = age;
32     }
33 }
 1 package com.hxl;
 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         // 先让两个对象的age属性做差比较,这个是主要排序条件
10         int num = s1.getAge() - s2.getAge();
11         // 若age属性相同,再比较name属性(String类本身实现了Comparable接口)
12         // 即在主要排序条件相同的情况下,次要排序条件起作用
13         int flag = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
14         // 返回比较结果
15         return flag;
16     }
17 }
 1 package com.hxl;
 2 
 3 import java.util.TreeSet;
 4 
 5 public class Test {
 6     public static void main(String[] args) {
 7         //这里使用TreeSet(Comparator comparator)构造实例化TreeSet集合,则启用的是指定比较器排序
 8         TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());
 9         ts.add(new Student("cc", 11));
10         ts.add(new Student("ee", 11));
11         ts.add(new Student("cc", 22));
12         ts.add(new Student("aa", 22));
13         ts.add(new Student("bb", 11));
14 
15         for (Student s : ts) {
16             System.out.println(s.getName()+"_"+s.getAge());
17         }
18     }
19 }

【比较器排序(内部类实现,如果只使用一次的话)】

 1 package com.hxl;
 2 
 3 public class Student{
 4 
 5     private String name;
 6     private int age;
 7 
 8     public Student() {
 9         super();
10     }
11 
12     public Student(String name, int age) {
13         super();
14         this.name = name;
15         this.age = age;
16     }
17 
18     public String getName() {
19         return name;
20     }
21 
22     public void setName(String name) {
23         this.name = name;
24     }
25 
26     public int getAge() {
27         return age;
28     }
29 
30     public void setAge(int age) {
31         this.age = age;
32     }
33 }
 1 package com.hxl;
 2 
 3 import java.util.Comparator;
 4 import java.util.TreeSet;
 5 
 6 public class Test {
 7     public static void main(String[] args) {
 8         //如果一个方法的参数是接口,那么真实想要的是其实是接口实现类的对象
 9         //这里的对象只用一次,专门定义一个外部类显得麻烦
10         //匿名内部类可以实现这个需求
11         TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
12             public int compare(Student s1, Student s2) {
13                 // 先让两个对象的age属性做差比较,这个是主要排序条件
14                 int num = s1.getAge() - s2.getAge();
15                 // 若age属性相同,再比较name属性(String类本身实现了Comparable接口)
16                 // 即在主要排序条件相同的情况下,次要排序条件起作用
17                 int flag = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
18                 // 返回比较结果
19                 return flag;
20             }
21         });
22         ts.add(new Student("cc", 11));
23         ts.add(new Student("ee", 11));
24         ts.add(new Student("cc", 22));
25         ts.add(new Student("aa", 22));
26         ts.add(new Student("bb", 11));
27 
28         for (Student s : ts) {
29             System.out.println(s.getName()+"_"+s.getAge());
30         }
31     }
32 }

 【注】开发中会用最后一种,因为第一种只有固定的排序方式,第二种每次都要定义外面类显得麻烦。

posted @ 2018-02-18 19:07  Schiller_Hu  阅读(1481)  评论(0编辑  收藏  举报