程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中天然排序和比擬器排序詳解

Java中天然排序和比擬器排序詳解

編輯:關於JAVA

Java中天然排序和比擬器排序詳解。本站提示廣大學習愛好者:(Java中天然排序和比擬器排序詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中天然排序和比擬器排序詳解正文


媒介

當指履行拔出排序、希爾排序、合並排序等算法時,比擬兩個對象“年夜小”的比擬操作。我們很輕易懂得整型的 i>j 如許的比擬方法,但當我們對多個對象停止排序時,若何比擬兩個對象的“年夜小”呢?如許的比擬 stu1 > stu2 明顯是弗成能經由過程編譯的。為懂得決若何比擬兩個對象年夜小的成績,JDK供給了兩個接口 java.lang.Comparable java.util.Comparator

1、天然排序:java.lang.Comparable

Comparable 接口中只供給了一個辦法: compareTo(Object obj) ,該辦法的前往值是 int 。假如前往值為負數,則表現以後對象(挪用該辦法的對象)比 obj 對象“年夜”;反之“小”;假如為零的話,則表現兩對象相等。

上面是一個完成了 Comparable 接口的 Student 類:

public class Student implements Comparable { 
 
 private int id; 
  
 private String name; 
 
 public Student() { 
  super(); 
 } 
 
 @Override 
 public int compareTo(Object obj) { 
  if (obj instanceof Student) { 
   Student stu = (Student) obj; 
   return id - stu.id; 
  } 
  return 0; 
 } 
 
 @Override 
 public String toString() { 
  return "<" + id + ", " + name + ">"; 
 } 
} 

Student 完成了天然排序接口 Comparable ,那末我們是怎樣應用這個接口對一組 Student 對象停止排序的呢?我們在進修數組的時刻,應用了一個類來給整型數組排序: java.util.Arrays 。我們應用 Arrays 的 sort 辦法來給整型數組排序。翻翻 API 文檔就會發明, Arrays 裡給出了 sort 辦法許多重載情勢,個中就包含 sort(Object[] obj) ,也就是說 Arryas 也能對對象數組停止排序,排序進程中比擬兩個對象“年夜小”時應用的就是 Comparable 接口的 compareTo 辦法。

public class CompareTest { 
 
 public static void main(String[] args) { 
  Student stu1 = new Student(1, "Little"); 
  Student stu2 = new Student(2, "Cyntin"); 
  Student stu3 = new Student(3, "Tony"); 
  Student stu4 = new Student(4, "Gemini"); 
   
  Student[] stus = new Student[4]; 
  stus[0] = stu1; 
  stus[1] = stu4; 
  stus[2] = stu3; 
  stus[3] = stu2; 
  System.out.println(“Array: ” + Arrays.toString(stus)); 
  Arrays.sort(stus); 
  System.out.println(“Sort: ” + Arrays.toString(stus)); 
 } 
} 

Student 數組裡添加元素的次序其實不是按學號 id 來添加的。挪用了 Arrays.sort(stus) 以後,對 Student 數組停止排序,不論 sort 是應用哪一種排序算法來完成的,比擬兩個對象“年夜小”這個操作,它是確定要做的。那末若何比擬兩個對象的“年夜小”? Student 完成的 Comparable 接口就施展感化了。 sort 辦法會將待比擬的誰人對象強迫類型轉換成 Comparable ,並挪用 compareTo 辦法,依據其前往值來斷定這兩個對象的“年夜小”。所以,在這個例子中排序後的原 Student 亂序數組就釀成了按學號排序的 Student 數組。

然則我們留意到,排序算法和 Student 類綁定了, Student 只要一種排序算法。但實際社會不是如許的,假如我們不想按學號排序怎樣辦?假設,我們想按姓名來給先生排序怎樣辦?我們只能修正 Student 類的 Comparable 接口的 compareTo 辦法,改成按姓名排序。假如在統一個體系裡有兩個操作,一個是按學號排序,別的一個是按姓名排序,這怎樣辦?弗成能在 Student 類體中寫兩個 compareTo 辦法的完成。這麼看來Comparable就有局限性了。為了填補這個缺乏,JDK 還為我們供給了別的一個排序方法,也就是上面要說的比擬器排序。

2、比擬器排序:java.util.Comparator

下面我提到了,之所以供給比擬器排序接口,是由於有時須要對統一對象停止多種分歧方法的排序,這點天然排序 Comparable 不克不及完成。別的, Comparator 接口的一個利益是將比擬排序算法和詳細的實體類分別了。

翻翻 API 會發明, Arrays.sort 還有種重載情勢:sort(T[] a, Comparator<? super T> c) ,這個辦法參數的寫法用到了泛型,我們還沒講到。我們可以把它懂得成如許的情勢: sort(Object[] a, Comparator c) ,這個辦法的意思是依照比擬器 c 給出的比擬排序算法,對 Object 數組停止排序。Comparator 接口中界說了兩個辦法: compare(Object o1, Object o2) equals 辦法,因為 equals 辦法一切對象都有的辦法,是以當我們完成 Comparator 接口時,我們只需重寫 compare 辦法,而不需重寫 equals 辦法。Comparator 接口中對重寫 equals 辦法的描寫是:“留意,不重寫 Object.equals(Object) 辦法老是平安的。但是,在某些情形下,重寫此辦法可以許可法式肯定兩個分歧的 Comparator 能否強行實行了雷同的排序,從而進步機能。”。我們只需曉得第一句話就OK了,也就是說,可以不消去想應當怎樣完成 equals 辦法,由於即便我們不顯示完成 equals 辦法,而是應用Object類的 equals 辦法,代碼仍然是平安的。

那末我們來寫個代碼,來用一用比擬器排序。照樣用 Student 類來做,只是沒有完成 Comparable 接口。因為比擬器的完成類只用顯示完成一個辦法,是以,我們可以不消專門寫一個類來完成它,當我們須要用到比擬器時,可以寫個匿名外部類來完成 Comparator 。

上面是我們的按姓名排序的辦法:

public void sortByName () { 
 Student stu1 = new Student(1, "Little"); 
 Student stu2 = new Student(2, "Cyntin"); 
 Student stu3 = new Student(3, "Tony"); 
 Student stu4 = new Student(4, "Gemini"); 
  
 Student[] stus = new Student[4]; 
 stus[0] = stu1; 
 stus[1] = stu4; 
 stus[2] = stu3; 
 stus[3] = stu2; 
 System.out.println("Array: " + Arrays.toString(stus)); 
 
 Arrays.sort(stus, new Comparator() { 
 
  @Override 
  public int compare(Object o1, Object o2) { 
   if (o1 instanceof Student && o2 instanceof Student) { 
    Student s1 = (Student) o1; 
    Student s2 = (Student) o2; 
    //return s1.getId() - s2.getId(); // 按Id排 
    return s1.getName().compareTo(s2.getName()); // 按姓名排 
   } 
   return 0; 
  } 
   
 }); 
  
 System.out.println("Sorted: " + Arrays.toString(stus)); 
} 

當我們須要對Student按學號排序時,只需修正我們的排序辦法中完成Comparator的外部類中的代碼,而不消修正 Student 類。

留意: 固然,你也能夠用 Student 類完成 Comparator 接口,如許Student就是(is a)比擬器了(Comparator)。當須要應用這類排序的時刻,將 Student 看做 Comparator 來應用便可以了,可以將 Student 作為參數傳入 sort 辦法,由於 Student is a Comparator 。但如許的代碼不是個優良的代碼,由於我們之所以應用比擬器(Comparator),個中有個主要的緣由就是,如許可以把比擬算法和詳細類分別,下降類之間的耦合。

TreeSet對這兩種比擬方法都供給了支撐,分離對應著TreeSet的兩個結構辦法:

     1、TreeSet():依據TreeSet中元素完成的 Comparable 接口的 compareTo 辦法比擬排序

   2、TreeSet(Comparator comparator):依據給定的 comparator 比擬器,對 TreeSet 中的元素比擬排序

當向 TreeSet 中添加元素時,TreeSet 就會對元素停止排序。至因而用天然排序照樣用比擬器排序,就看你的 TreeSet 結構是怎樣寫的了。固然,添加第一個元素時不會停止任何比擬, TreeSet 中都沒有元素,和誰比去啊?

上面,分離給出應用兩種排序比擬方法的 TreeSet 測試代碼:

/** 
 * 應用天然排序 
 * Student必需完成Comparable接口,不然會拋出ClassCastException 
 */ 
public void testSortedSet3() { 
 Student stu1 = new Student(1, "Little"); 
 Student stu2 = new Student(2, "Cyntin"); 
 Student stu3 = new Student(3, "Tony"); 
 Student stu4 = new Student(4, "Gemini"); 
 
 SortedSet set = new TreeSet(); 
 set.add(stu1); 
 set.add(stu3); // 若Student沒有完成Comparable接口,拋出ClassCastException 
 set.add(stu4); 
 set.add(stu2); 
 set.add(stu4); 
 set.add(new Student(12, "Little")); 
 
 System.out.println(set); 
} 
/** 
 * 應用比擬器排序 
 * Student可以只是個簡略的Java類,不消完成Comparable接口 
 */ 
public void testSortedSet3() { 
 Student stu1 = new Student(1, "Little"); 
 Student stu2 = new Student(2, "Cyntin"); 
 Student stu3 = new Student(3, "Tony"); 
 Student stu4 = new Student(4, "Gemini"); 
 
 SortedSet set = new TreeSet(new Comparator() { 
 
  @Override 
  public int compare(Object o1, Object o2) { 
   if (o1 instanceof Student 
     && o2 instanceof Student) { 
    Student s1 = (Student) o1; 
    Student s2 = (Student) o2; 
    return s1.getName().compareTo(s2.getName()); 
   } 
   return 0; 
  } 
   
 }); 
 
 set.add(stu1); 
 set.add(stu3); 
 set.add(stu4); 
 set.add(stu2); 
 set.add(stu4); 
 set.add(new Student(12, "Little")); 
 
 System.out.println(set); 
} 

別的,引見個對象類,java.util.Collections。留意,這不是Collection接口。Collections很像Arrays類。Arrays供給了一系列用於對數組操作的靜態辦法,查找排序等等。Collections也供給了一系列如許的辦法,只是它是用於處置聚集的,固然Collections類和Collection接口很像,然則不要被Collections的名字給誘騙了,它不是只能處置Collection接口和子接口的完成類,異樣也能夠處置Map接口的完成類。

總結

Java中天然排序和比擬器排序的引見就到這裡了,文章引見的照樣絕對具體的,願望能對年夜家的進修或許任務帶來必定的贊助,假如有疑問年夜家可以留言交換。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved