JAVA编程思想学习 — JAVA中通用排序的具体做法
2017-09-12 14:47
330 查看
编写通用的排序代码时,面临的一个问题是必须根据对象的实际类型来执行比较运算,从而实现正确的排 序。当然,一个办法是为每种不同的类型都写一个不同的排序方法。然而,应认识到假若这样做,以后增加 新类型时便不易实现代码的重复利用。
程序设计一个主要的目标就是“将发生变化的东西同保持不变的东西分隔开”。在这里,保持不变的代码是 通用的排序算法,而每次使用时都要变化的是对象的实际比较方法。因此,我们不可将比较代码“硬编码” 到多个不同的排序例程内,而是采用“回调”技术。利用回调,经常发生变化的那部分代码会封装到它自己
的类内,而总是保持相同的代码则“回调”发生变化的代码。这样一来,不同的对象就可以表达不同的比较 方式,同时向它们传递相同的排序代码。
下面这个“接口”( Interface)展示了如何比较两个对象,它将那些“要发生变化的东西”封装在内(摘自JAVA编程思想 第四版 第八章):
对这两种方法来说, lhs 代表本次比较中的“左手”对象,而 rhs 代表“右手”对象。(如果对这一部分不理解的同学,请自行学习 数据结构--快速排序)
下面是快速排序的过程
现在,大家可以明白“ 回调”一词的来历,这是由于 quickSort()方法“往回调用”了 Compare 中的方法。 从中亦可理解这种技术如何生成通用的、可重复利用(再生)的代码。
为使用 SortVector,必须创建一个类,令其为我们准备排序的对象实现 Compare。此时内部类并不显得特别 重要,但对于代码的组织却是有益的。下面是针对 String 对象的一个例子:
内部类是“静态”( Static)的,因为它毋需连接一个外部类即可工作。 大家可以看到,一旦设置好框架,就可以非常方便地重复使用象这样的一个设计—— 只需简单地写一个类, 将“需要发生变化”的东西封装进去,然后将一个对象传给SortVector 即可。
Java中实现排序的流程是,将不变的代码部分封装起来,将需要经常改变的部分(两个参数的比较等)封装到自己的类中,这也就是为什么需要用到排序功能是一定要实现Comparable 的原因.
最近在看JAVA编程思想(第四版)这本书,将书中的一些知识点容易遇到或者混淆的概念记录下来,只是作为备忘,希望也能帮到需要的人,特此申明.
程序设计一个主要的目标就是“将发生变化的东西同保持不变的东西分隔开”。在这里,保持不变的代码是 通用的排序算法,而每次使用时都要变化的是对象的实际比较方法。因此,我们不可将比较代码“硬编码” 到多个不同的排序例程内,而是采用“回调”技术。利用回调,经常发生变化的那部分代码会封装到它自己
的类内,而总是保持相同的代码则“回调”发生变化的代码。这样一来,不同的对象就可以表达不同的比较 方式,同时向它们传递相同的排序代码。
下面这个“接口”( 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 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); } } ///:~
现在,大家可以明白“ 回调”一词的来历,这是由于 quickSort()方法“往回调用”了 Compare 中的方法。 从中亦可理解这种技术如何生成通用的、可重复利用(再生)的代码。
为使用 SortVector,必须创建一个类,令其为我们准备排序的对象实现 Compare。此时内部类并不显得特别 重要,但对于代码的组织却是有益的。下面是针对 String 对象的一个例子:
//: 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()); } } ///:~
内部类是“静态”( Static)的,因为它毋需连接一个外部类即可工作。 大家可以看到,一旦设置好框架,就可以非常方便地重复使用象这样的一个设计—— 只需简单地写一个类, 将“需要发生变化”的东西封装进去,然后将一个对象传给SortVector 即可。
Java中实现排序的流程是,将不变的代码部分封装起来,将需要经常改变的部分(两个参数的比较等)封装到自己的类中,这也就是为什么需要用到排序功能是一定要实现Comparable 的原因.
最近在看JAVA编程思想(第四版)这本书,将书中的一些知识点容易遇到或者混淆的概念记录下来,只是作为备忘,希望也能帮到需要的人,特此申明.
相关文章推荐
- 学习java编程思想
- JAVA编程思想学习笔记(一)
- Java 编程思想(第四版)学习笔记(4 )控制执行流程
- Java编程思想 (第4版)读后感_学习Java编程最佳书籍
- Java 编程思想(第四版)学习笔记(8)多态
- java网络编程的具体学习方向
- Java编程思想学习笔记——枚举、注解
- java编程思想学习笔记 泛化的class引用
- 【学习笔记⑧】JAVA编程思想学习笔记
- Java 编程思想(第四版)学习笔记(6)访问权限控制
- JAVA编程思想学习第一篇の对象导论
- java编程思想3感悟(4)---被隐藏的具体实现
- Go学习笔记 - 关于Java、Python、Go编程思想的不同
- Java编程思想学习一——基础概念
- JAVA编程思想学习笔记
- JAVA编程思想学习第二篇の一切都是对象
- java编程思想学习笔记(一)
- java编程思想学习(1)
- java编程思想学习笔记(二)
- Java 编程思想(第四版)学习笔记(3)操作符