JAVA编程思想学习 — JAVA中通用排序的具体做法

来源:互联网 发布:百慕大三角知乎 编辑:程序博客网 时间:2024/05/18 18:18
编写通用的排序代码时,面临的一个问题是必须根据对象的实际类型来执行比较运算,从而实现正确的排 序。当然,一个办法是为每种不同的类型都写一个不同的排序方法。然而,应认识到假若这样做,以后增加 新类型时便不易实现代码的重复利用。
     程序设计一个主要的目标就是“将发生变化的东西同保持不变的东西分隔开”。在这里,保持不变的代码是 通用的排序算法,而每次使用时都要变化的是对象的实际比较方法。因此,我们不可将比较代码“硬编码” 到多个不同的排序例程内,而是采用“回调”技术。利用回调,经常发生变化的那部分代码会封装到它自己 的类内,而总是保持相同的代码则“回调”发生变化的代码这样一来,不同的对象就可以表达不同的比较 方式,同时向它们传递相同的排序代码。

     下面这个“接口”( Interface)展示了如何比较两个对象,它将那些“要发生变化的东西”封装在内(摘自JAVA编程思想 第四版 第八章): 

//: Compare.java// Interface for sorting callback:package c08;interface Compare {  boolean lessThan(Object lhs, Object rhs);  boolean lessThanOrEqual(Object lhs, Object rhs);} ///:~

 对这两种方法来说, lhs 代表本次比较中的“左手”对象,而 rhs 代表“右手”对象。(如果对这一部分不理解的同学,请自行学习 数据结构--快速排序)

下面是快速排序的过程 
//: SortVector.java// A generic sorting vectorpackage 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);  }} ///:~

现在,大家可以明白“ 回调”一词的来历,这是由于 quickSort()方法“往回调用”了 Compare 中的方法。 从中亦可理解这种技术如何生成通用的、可重复利用(再生)的代码。
     为使用 SortVector,必须创建一个类,令其为我们准备排序的对象实现 Compare。此时内部类并不显得特别 重要,但对于代码的组织却是有益的。下面是针对 String 对象的一个例子:
//: StringSortTest.java// Testing the generic sorting Vectorpackage 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());  }} ///:~

内部类是“静态”( Static)的,因为它毋需连接一个外部类即可工作。 大家可以看到,一旦设置好框架,就可以非常方便地重复使用象这样的一个设计—— 只需简单地写一个类, 将“需要发生变化”的东西封装进去,然后将一个对象传给SortVector 即可。

    Java中实现排序的流程是,将不变的代码部分封装起来,将需要经常改变的部分(两个参数的比较等)封装到自己的类中,这也就是为什么需要用到排序功能是一定要实现Comparable 的原因.

最近在看JAVA编程思想(第四版)这本书,将书中的一些知识点容易遇到或者混淆的概念记录下来,只是作为备忘,希望也能帮到需要的人,特此申明.

原创粉丝点击