1. 程式人生 > >Java中如何使用排序詳解

Java中如何使用排序詳解

1.問題的提出

  在前面的文章中已經總結了資料結構中的八大基本排序方法,因為平時主要使用Java語言進行開發,因此想到在Java中使用的是哪一種排序方法呢?快速排序還是歸併排序,或是其它》又該怎麼使用它們呢?

2.基本型別的排序

  一提到Java中的排序方法,自然想到的是sort()方法。在JDK中,擁有sort()方法的類主要有java.util.Arrays和java.util.Collections(注意和Collection介面的區別)。
  jdk中的sort

Arrays.sort()

  Java中的Arrays.sort()主要採用了兩種排序方法,分別是快速排序和優化之後的歸併排序。其中快速排序主要是對於基本資料型別(int,short,long等),而歸併排序主要用於物件型別。
  為什麼要這樣區分開呢?這主要是考慮到不同的排序需求。我們知道,排序方法分為穩定

不穩定,我們知道快速排序是不穩定的,歸併排序是穩定的。
  對於基本資料型別如int,兩個int型的4,4進行排序,誰前誰後都沒有特別的意義,所以使用快速排序。而對於物件型別,一個物件可能有多個屬性,我們很可能只是根據它們其中的一個關鍵屬性進行排序,那麼,最好保持相等物件的非關鍵屬性的順序與排序前一致,所以這種情況使用歸併排序。
  另外一個原因是由於歸併排序相對而言比較次數比快速排序少,移動(物件引用的移動)次數比快速排序多,而對於物件來說,比較一般比移動耗時,因此選擇歸併排序。
  歸併排序的時間複雜度是O(nlogn), 快速排序的平均時間複雜度也是O(nlogn),但是歸併排序的需要額外的n個引用的空間。

Collections.sort()

  Java中的Collections.sort()採用的是歸併排序,是穩定的排序方法,當待排序咧接近有序的時候,效率更高。
  問題:既然Arrays和Collections都可以實現排序,那麼它們有什麼區別,在什麼情況下該使用哪一個呢?
  一般的,在待排序序列是基本資料型別時(物件型別稍後講述),我們通常使用Arrays對陣列進行排序,使用Collections對集合框架容器進行排序,如List。
  比如:

int[] intArray = new int[] {4,1,3,-23};
Arrays.sort(intArray);
//輸出結果為:-23
,1,3,4 String[] strArray = new String[] {"z","a","C"}; Arrays.sort(strArray); //輸出結果為:C,a,z Arrays.sort(strArray,String.CASE_INSENSITIVE_ORDER); //輸出結果為:a,C,z //Arrays.sort方法只能按照升序排列,其本身沒有reverse這樣的方法,但是可以通過設定比較器進行降序排列 //此處可以藉助Collections.reverseOrder()這個比較器實現降序排列 Arrays.sort(strArray,Collections.reverseOrder()); //輸出結果為:z,a,C Arrays.sort(strArray,String.CASE_INSENSITIVE_ORDER); Collections.reverse(Arrays.asList(strArray)); //輸出結果為:z,C,a

  當然,我們也可以指定對陣列的某一段進行排序:Arrays.sort(strArray,0,2);這樣我們只對前三個元素進行排序,不會影響到後面部分的順序。
  Collections.sort()當然也可以實現對基本資料型別序列的排序,只需要將待排序序列放到一個List中就可以了。

List<Integer> intList = new ArrayList<Integer>();
intList.add(3);
intList.add(23);
intList.add(-1);
Collections.sort(intList);

  由於此處是對基本資料型別進行排序,而且Collections有自己的降序方法,所以不需要比較器。只有在下面講述的對物件型別進行排序的時候才用到比較器。

3.物件型別的排序

  問題:上面講的都是對基本資料型別的排序,那麼當待排序序列為物件的時候該怎麼辦呢?下面我們就來看看Arrays.sort()和Collections.sort()分別是怎麼運用才能對物件型別進行排序。

Comparable介面&Comparator介面

  Comparable介面之中只有一個方法compareTo(),如果一個物件要要實現可排序,在實現了Comparable介面後,必須在物件內部重寫compareTo方法(即定義自己需要的排序規則),因此我們稱Comparable是在物件內部需要實現的介面;與此對應,Comparator介面是在物件外實現的介面,不需要在物件內部定義排序規則。這主要是方便對沒有實現Comparable介面的物件進行比較和排序。
  Comparable介面使用示例:

public class User implements Comparable<Object> {
private String id;
private int age;
public User(String id, int age) {
this.id = id;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//定義自己需要的排序規則
//規則為:按照年齡對物件進行排序,若返回負數,當前物件的年齡比被比較物件年齡小,排序方法會將較小的放在前面
public int compareTo(Object o) {
int result;
result = this.age - ((User) o).getAge();
return result;
}
public static void main(String[] args) {
User[] userArray = new User[] {new User("0003",19),new User("0004",21),new User("0009",17)};
Arrays.sort(userArray);
//排序結果為("0009",17),("0003",19),("0004",21)
}
}

  Comparator介面使用示例:

public class User {
private String id;
private int age;
public User(String id, int age) {
this.id = id;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

public class NewComparator implements Comparator<Object>{

//該方法返回一個基本型別的整型,返回負數表示o1 小於o2,返回0 表示o1和o2相等,返回正數表示o1大於o2。 
//在物件外部定義排序規則
public int compare(Object o1, Object o2) {
User u1 = (User) o1;
User u2 = (User) o2;
return u1.getAge() - u2.getAge();
}

}

public class TestSort {

public static void main(String[] args) {
User[] userArray = new User[] {new User("0003",19),new User("0004",21),
new User("0009",17)};
//由於User沒有實現Comparable介面,需要使用一個比較器來對物件進行比較
Arrays.sort(userArray,new NewComparator());
//排序結果為:("0009",17),("0003",19),("0004",21)
}

}

總結及比較

  Comparable是通用的介面,使用者可以實現它來完成自己特定的比較,而Comparator可以看成一種演算法的實現,在需要容器集合collection需要比較功能的時候,來指定這個比較器,這可以看出一種設計模式,將演算法和資料分離。
  前者應該比較固定,和一個具體類相繫結,而後者比較靈活,它可以被用於各個需要比較功能的類使用。可以說前者屬於“靜態繫結”,而後者可以“動態繫結”。
  一個類實現了Camparable介面表明這個類的物件之間是可以相互比較的。如果用數學語言描述的話就是這個類的物件組成的集合中存在一個全序。這樣,這個類物件組成的集合就可以使用Sort方法排序了。
  而Comparator的作用主要是以下兩個:
  1)如果類的設計師沒有考慮到Compare的問題而沒有實現Comparable介面,可以通過Comparator來實現比較演算法進行排序。
  2)為了使用不同的排序標準做準備,比如:升序、降序或其他什麼序。

4.參考