国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Java中的排序

2019-11-18 13:22:15
字體:
供稿:網(wǎng)友

  java 1.0和1.1庫都缺少的一樣?xùn)|西是算術(shù)運(yùn)算,甚至沒有最簡單的排序運(yùn)算方法。因此,我們最好創(chuàng)建一個(gè)Vector,利用經(jīng)典的Quicksort(快速排序)方法對(duì)其自身進(jìn)行排序。
  編寫通用的排序代碼時(shí),面臨的一個(gè)問題是必須根據(jù)對(duì)象的實(shí)際類型來執(zhí)行比較運(yùn)算,從而實(shí)現(xiàn)正確的排序。當(dāng)然,一個(gè)辦法是為每種不同的類型都寫一個(gè)不同的排序方法。然而,應(yīng)熟悉到假若這樣做,以后增加新類型時(shí)便不易實(shí)現(xiàn)代碼的重復(fù)利用。
  程序設(shè)計(jì)一個(gè)主要的目標(biāo)就是“將發(fā)生變化的東西同保持不變的東西分隔開”。在這里,保持不變的代碼是通用的排序算法,而每次使用時(shí)都要變化的是對(duì)象的實(shí)際比較方法。因此,我們不可將比較代碼“硬編碼”到多個(gè)不同的排序例程內(nèi),而是采用“回調(diào)”技術(shù)。利用回調(diào),經(jīng)常發(fā)生變化的那部分代碼會(huì)封裝到它自己的類內(nèi),而總是保持相同的代碼則“回調(diào)”發(fā)生變化的代碼。這樣一來,不同的對(duì)象就可以表達(dá)不同的比較方式,同時(shí)向它們傳遞相同的排序代碼。
  下面這個(gè)“接口”(Interface)展示了如何比較兩個(gè)對(duì)象,它將那些“要發(fā)生變化的東西”封裝在內(nèi):
  
  //: Compare.java
  // Interface for sorting callback:
  package c08;
  
  interface Compare {
   boolean lessThan(Object lhs, Object rhs);
   boolean lessThanOrEqual(Object lhs, Object rhs);
  } ///:~
  
  對(duì)這兩種方法來說,lhs代表本次比較中的“左手”對(duì)象,而rhs代表“右手”對(duì)象。
  可創(chuàng)建Vector的一個(gè)子類,通過Compare實(shí)現(xiàn)“快速排序”。對(duì)于這種算法,包括它的速度以及原理等等,在此不具體說明。欲知詳情,可參考Binstock和Rex編著的《PRactical Algorithms for Programmers》,由Addison-Wesley于1995年出版。
  
  //: SortVector.java
  // A generic sorting vector
  package c08;
  import java.util.*;
  
  public class SortVector extends Vector {
   private Compare compare; // To hold the callback
   public SortVector(Compare comp) {
    compare = comp;
   }
   public void sort() {
    quickSort(0, size() - 1);
   }
   private void quickSort(int left, int right) {
    if(right > left) {
     Object o1 = elementAt(right);
     int i = left - 1;
     int j = right;
     while(true) {
      while(compare.lessThan(
         elementAt(++i), o1))
       ;
      while(j > 0)
       if(compare.lessThanOrEqual(
         elementAt(--j), o1))
        break; // out of while
      if(i >= j) break;
      swap(i, j);
     }
     swap(i , right);
     quickSort(left, i-1);
     quickSort(i+1, right);
    }
   }
   private void swap(int loc1, int loc2) {
    Object tmp = elementAt(loc1);
    setElementAt(elementAt(loc2), loc1);
    setElementAt(tmp, loc2);
   }
  } ///:~
  
  現(xiàn)在,大家可以明白“回調(diào)”一詞的來歷,這是由于quickSort()方法“往回調(diào)用”了Compare中的方法。從中亦可理解這種技術(shù)如何生成通用的、可重復(fù)利用(再生)的代碼。
  為使用SortVector,必須創(chuàng)建一個(gè)類,令其為我們預(yù)備排序的對(duì)象實(shí)現(xiàn)Compare。此時(shí)內(nèi)部類并不顯得非凡重要,但對(duì)于代碼的組織卻是有益的。下面是針對(duì)String對(duì)象的一個(gè)例子:
  
  //: StringSortTest.java
  // Testing the generic sorting Vector
  package c08;
  import java.util.*;
  
  public class StringSortTest {
   static class StringCompare implements Compare {
    public boolean lessThan(Object l, Object r) {
     return ((String)l).toLowerCase().compareTo(
      ((String)r).toLowerCase()) < 0;
    }
    public boolean
    lessThanOrEqual(Object l, Object r) {
     return ((String)l).toLowerCase().compareTo(
      ((String)r).toLowerCase()) <= 0;
    }
   }
   public static void main(String[] args) {
    SortVector sv =
     new SortVector(new StringCompare());
    sv.addElement("d");
    sv.addElement("A");
    sv.addElement("C");
    sv.addElement("c");
    sv.addElement("b");
    sv.addElement("B");
    sv.addElement("D");
    sv.addElement("a");
    sv.sort();
    Enumeration e = sv.elements();
    while(e.hasMoreElements())
     System.out.println(e.nextElement());
   }
  } ///:~
  
  內(nèi)部類是“靜態(tài)”(Static)的,因?yàn)樗阈柽B接一個(gè)外部類即可工作。
  大家可以看到,一旦設(shè)置好框架,就可以非常方便地重復(fù)使用象這樣的一個(gè)設(shè)計(jì)——只需簡單地寫一個(gè)類,將“需要發(fā)生變化”的東西封裝進(jìn)去,然后將一個(gè)對(duì)象傳給SortVector即可。
  比較時(shí)將字串強(qiáng)制為小寫形式,所以大寫A會(huì)排列于小寫a的旁邊,而不會(huì)移動(dòng)一個(gè)完全不同的地方。然而,該例也顯示了這種方法的一個(gè)不足,因?yàn)樯鲜鰷y(cè)試代碼按照出現(xiàn)順序排列同一個(gè)字母的大寫和小寫形式:A a b B c C d D。但這通常不是一個(gè)大問題,因?yàn)榻?jīng)常處理的都是更長的字串,所以上述效果不會(huì)顯露出來(Java 1.2的集合提供了排序功能,已解決了這個(gè)問題)。
  繼續(xù)(extends)在這兒用于創(chuàng)建一種新類型的Vector——也就是說,SortVector屬于一種Vector,并帶有一些附加的功能。繼續(xù)在這里可發(fā)揮很大的作用,但了帶來了問題。它使一些方法具有了final屬性(已在第7章講述),所以不能覆蓋它們。假如想創(chuàng)建一個(gè)排好序的Vector,令其只接收和生成String對(duì)象,就會(huì)碰到麻煩。因?yàn)閍ddElement()和elementAt()都具有final屬性,而且它們都是我們必須覆蓋的方法,否則便無法實(shí)現(xiàn)只能接收和產(chǎn)生String對(duì)象。
  但在另一方面,請(qǐng)考慮采用“合成”方法:將一個(gè)對(duì)象置入一個(gè)新類的內(nèi)部。此時(shí),不是改寫上述代碼來達(dá)到這個(gè)目的,而是在新類里簡單地使用一個(gè)SortVector。在這種情況下,用于實(shí)現(xiàn)Compare接口的內(nèi)部類就可以“匿名”地創(chuàng)建。如下所示:
  
  //: StrSortVector.java
  // Automatically sorted Vector that
  // accepts and prodUCes only Strings
  package c08;
  import java.util.*;
  
  public class StrSortVector {
   private SortVector v = new SortVector(
    // Anonymous inner class:
    new Compare() {
     public boolean
     lessThan(Object l, Object r) {
      return
       ((String)l).toLowerCase().compareTo(
       ((String)r).toLowerCase()) < 0;
     }
     public boolean
     lessThanOrEqual(Object l, Object r) {
      return
       ((String)l).toLowerCase().compareTo(
       ((String)r).toLowerCase()) <= 0;
     }
    }
   );
   private boolean sorted = false;
   public void addElement(String s) {
    v.addElement(s);
    sorted = false;
   }
   public String elementAt(int index) {
    if(!sorted) {
     v.sort();
     sorted = true;
    }
    return (String)v.elementAt(index);
   }
   public Enumeration elements() {
    if(!sorted) {
     v.sort();
     sorted = true;
    }
    return v.elements();
   }
   // Test it:
   public static void main(String[] args) {
    StrSortVector sv = new StrSortVector();
    sv.addElement("d");
    sv.addElement("A");
    sv.addElement("C");
    sv.addElement("c");
    sv.addElement("b");
    sv.addElement("B");
    sv.addElement("D");
    sv.addElement("a");
    Enumeration e = sv.elements();
    while(e.hasMoreElements())
     System.out.println(e.nextElement());
   }
  } ///:~
  
  這樣便可快速再生來自SortVector的代碼,從而獲得希望的功能。然而,并不是來自SortVector和Vector的所有public方法都能在StrSortVector中出現(xiàn)。若按這種形式再生代碼,可在新類里為包含類內(nèi)的每一個(gè)方法都生成一個(gè)定義。當(dāng)然,也可以在剛開始時(shí)只添加少數(shù)幾個(gè),以后根據(jù)需要再添加更多的。新類的設(shè)計(jì)最終會(huì)穩(wěn)定下來。
  這種方法的好處在于它仍然只接納String對(duì)象,也只產(chǎn)生String對(duì)象。而且相應(yīng)的檢查是在編譯期間進(jìn)行的,而非在運(yùn)行期。當(dāng)然,只有addElement()和elementAt()才具備這一特性;elements()仍然會(huì)產(chǎn)生一個(gè)Enumeration(枚舉),它在編譯期的類型是未定的。當(dāng)然,對(duì)Enumeration以及在StrSortVector中的類型檢查會(huì)照舊進(jìn)行;假如真的有什么錯(cuò)誤,運(yùn)行期間會(huì)簡單地產(chǎn)生一個(gè)違例。事實(shí)上,我們?cè)诰幾g或運(yùn)行期間能保

上一篇:Java中的Vector

下一篇:再論枚舉器

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 长乐市| 隆德县| 锦州市| 惠东县| 革吉县| 莎车县| 康保县| 德钦县| 汾西县| 醴陵市| 富源县| 阜宁县| 白山市| 林甸县| 阿拉善左旗| 诏安县| 邵东县| 平潭县| 鄂托克前旗| 金乡县| 阿拉善右旗| 凤阳县| 碌曲县| 若尔盖县| 龙陵县| 沂南县| 山阴县| 普安县| 云安县| 汪清县| 汶川县| 湄潭县| 台东市| 衡南县| 亳州市| 台北市| 黑水县| 句容市| 莱州市| 柞水县| 台南市|