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]

 

 

 

 


免責聲明!

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



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