2012-04-04 72 views
3

我最近一直致力於更好地理解排序算法及其與不同類型輸入的關係。目前,我正在學習管理課程,每個學生都有三個參數:姓氏,GPA和用戶ID(字符串,雙精度,整數)。它們每個都存儲在具有這三個參數的Student類中,並且有DOZENS的學生(該程序的關鍵特徵是輸入,移除和更新學生)。Java對多個參數進行排序對象

我的問題是:使用的主要排序算法(歸併排序,快速排序等),什麼是每個參數排序我的學生名單的最佳方式?例如,執行合併排序以按GPA排序列表的最佳方式是什麼?或者使用快速排序按姓氏排序列表?

基本上我的問題可以歸結爲...我可以,如果他們沒有三個參數(寫一個合併100個號碼排序是非常容易的事情),這些對象進行排序。如何管理其他兩個參數並確保在排序後可以訪問?

+0

這是功課? – 2012-04-04 17:46:31

+0

作業分配(到幾周前)是要學習如何對mergesort進行硬編碼以對100個整數列表進行排序。我只是想了解當我開始處理更大的項目時Java工具的侷限性。 – MattDavBen 2012-04-04 17:48:12

回答

5

這是Java做的方法是使用不同Comparators。然後你說:

Collections.sort(list, new NameComparator()); 

或者

Collections.sort(list, new GpaComparator()); 

這些比較使用不同的字段來定義兩個元素之間的順序。

例如,名稱比較可能是:

class NameComparator implements Comparator< Student> { 
    @Override public int compare(Student left, Student right) { 
     return left.getName().compareTo(right.getName()); 
    } 
} 

而且GpaComparator可能是

class GpaComparator implements Comparator< Student> { 
    @Override public int compare(Student left, Student right) { 
     if (left.getGpa() < right.getGpa()) { 
      return -1; 
     } else if (left.getGpa() > right.getGpa()) { 
      return 1; 
     } else { 
      return 0; 
    } 
} 
+0

編寫'GPAComparator'的更好方法是使用'Integer'對象而不是原語,並僅僅委託給'.compare()'方法。然後'if/elseif/else'塊變成單行。 – 2012-04-04 18:29:29

0

這真的沒有比排序號的不同,不同的是在這種情況下,你的「數字」是三個字段中輸入您的用戶,每一個數字的值是由每個字段的值約束和字段的順序確定排序等級。

爲了更具體一點,你有一個Tupple有3個字段:<GPA, Last Name, User ID>,讓我們假設你想按GPA排序,然後是Last Name和User ID。

以與219在139以上分類相同的方式(即「數百」數字具有較高值,即使「數十」數字較低),類似<3.75, Jones, 5>的花紋將排序在<3.0, Adams, 2>之上,因爲「GPA數字「(這更顯着)具有較高的價值,即使」姓氏數字「較低(例如,瓊斯比」亞當斯「低」)。

1

我會建議實施Comparable接口在Student類這樣

public class Student implements Comparable { 
    public int compareType; //you can make this an enum if you want 
    ... 

    public int compareTo(Object o) { 
     if(compareType == 0) 
     return gpaCompareTo(o); 
     else if(compareType == 1) 
     return nameCompareTo(o); 

     return idCompateTo(o); 
    } 

    public int gpaCompareTo(Object o) { 
     //implement your gpaCompareTo 
    } 

    public int nameCompareTo(Object o) { 
     //implement your nameCompareTo 
    } 

    public int idCompareTo(Object o) { 
     //implement your idCompareTo 
    } 
} 

,然後使用內置的有點像

List<Student> list = new ArrayList<Student>(); 
... 
Collections.sort(list); 

,或者無法實現Comparable和設計自己的比較

public class MyComparator implements Comparator<Student> { 

    public int compare(Student o1, Student o2) { 
     //implement the comparator 
    } 

    public boolean equals(Object o) { 
     //implement the equals 
    } 
} 

然後你可以使用其他Collection's排序方法

Collections.sort(list, MyComparator); 
+1

「Comparable」只有在你每次都用同樣的東西排序時纔有效。 – 2012-04-04 17:49:26

+0

@LouisWasserman true我將澄清 – twain249 2012-04-04 17:50:39

1

的典型方法做,這是寫在任何類型的接受Comparator一個通用的排序算法,然後寫不同Comparator S按不同的字段進行排序。

1

這可能是題外話,但如果你想嘗試一些很酷的東西,在JDK 8 Lambda Preview提供了一些很酷的方法來使用Lamda expressions and method references定義比較器。

比方說,我們有一個類:

class Jedi { 
    private final String name; 
    private final int age; 
    //... 
} 

,然後將它們的集合:

List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30)); 
sort(jediAcademy, (j1, j2) -> j1.getAge() > j2.getAge() ? 1 : j1.getAge() < j2.getAge() ? -1 : 0); 
System.out.println(jediAcademy); //Anakin, Obiwan 

或者與方法的引用,假設絕地有表現爲比較器(相同的簽名)方法

class Jedi { 
    public static int compareByAge(Jedi first, Jedi second){ 
    return first.age > second.age ? 1 : first.age < second.age ? -1 : 0; 
    } 
    //... 
} 

可以如下使用它們來使用方法生成比較器: d參考:

List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30)); 
sort(jediAcademy, Jedi::compareByAge); 
System.out.println(jediAcademy);//Anakin, Obiwan 
+0

+1:關於比較器的非常酷的方法。我想我們很快會看到像這樣深深融合的東西。非常容易使用。 – MattDavBen 2012-04-05 01:42:39

+0

@Mathew事實上,你可以通過下載和安裝我上面共享的預覽試試看:-) – 2012-04-05 02:31:03

0

使用多個比較

class Student 
{ 

     String lastName; 
     dounle GPA; 
     int userId 


    static Comparator<Student> getStudentLastNameComparator() { 
     return new Comparator<Student>() { 

      @Override 
      public int compare(Student Student1, Student Student2) { 
       return Student1.getlastName().compareTo(Student2.getlastName()); 
      } 
      // compare using Student lastName 
     }; 
    } 

    static Comparator<Student> getStudentGPAComparator() { 
     return new Comparator<Student>() { 

      @Override 
      public int compare(Student Student1, Student Student2) { 
       if(Student1.GPA < Student2.GPA) 
        return 1; 
       else 
        return -1; 
      } 
      // compare using Student GPA 
     }; 
    } 

    static Comparator<Student> getStudentUserIdComparator() { 
     return new Comparator<Student>() { 

      @Override 
      public int compare(Student Student1, Student Student2) { 
       if(Student1.userId < Student2.userId) 
        return 1; 
       else 
        return -1; 
      } 
      // compare using Student userId 
     }; 
    } 
}