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方法

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM