|  | 
 
| 众所周知,如果需要在 Java 中使用排序方法,那么就需要实现 
 Comparable 接口。
 
 
 public interface java.lang.Comparable {
 
 public int compareTo(Object o);
 
 }
 
 
 
 
 
 
 Comparable 接口很简单,因为它只有一个方法;然而如果你需要根据多
 
 个属性对对象进行排序,那么实现 compareTo 方法就会变得很复杂。
 
 
 下边就是一个摘自 Jakarta Commons cookbook 的例子:
 
 
 package com.discursive.jccook.collections.compare;
 
 
 import java.util.*;
 
 
 import org.apache.commons.lang.StringUtils;
 
 
 import org.apache.commons.collections.comparators.ReverseComparator;
 
 
 
 public class BookComparator implements Comparator {
 
 
 public int compare(Object o1, Object o2) {
 
 
 int comparison = -1;
 
 
 if( o1 instanceof Book && o2 instanceof Book ) {
 
 
 
 Book b1 = (Book) o1;
 
 
 Book b2 = (Book) o2;
 
 
 String b1Name = b1.getName( );
 
 
 String b2Name = b2.getName( );
 
 
 String b1Author = b1.getAuthor( );
 
 
 String b2Author = b2.getAuthor( );
 
 
 if( StringUtils.isNotEmpty( b1Name ) &&
 
 
 StringUtils.isNotEmpty( b2Name ) ) {
 
 
 comparison = b1Name.compareTo( b2Name );
 
 
 }
 
 
 if( comparison == 0 &&
 
 
 StringUtils.isNotEmpty( b1Author ) &&
 
 
 StringUtils.isNotEmpty( b2Author ) ) {
 
 
 comparison = b1Author.compareTo( b2Author );
 
 
 }
 
 
 }
 
 
 return comparison;
 
 
 }
 
 
 }
 
 
 该事例是对一个称为 book 的 bean 进行排序,将会根据 name 和 author
 
 两个属性进行排序。当我们使用的时候,就可以类似于以下的形式。
 
 
 Arrary.sort(books,BookComparator) 或者 collections.sort
 
 (books,BookComparator). 当中的两个参数是要排序的数组或者 list 以及使
 
 用的 Comparator 。下边主要说的就是怎样构造 Comparator 。
 
 
 本文的是展示怎样使用 commons 的组件,来完成 Comparator 的构造。
 
 
 对单一 bean 的单个属性排序
 
 
 现在如果我们只是想对 bean 中的一个属性进行排序的话。那么只需要构造
 
 出一个 BeanComparator 的实例就可以了 .
 
 
 形式如下:
 
 
 private BeanComparator comparator = new BeanComparator("name");
 
 
 这样子我们就构造出了一个根据 ”name” 属性来对集合中的 bean 进行排
 
 序的比较器。当集合中的 bean 有 name 这个属性的时候,那么排序时就会依照
 
 这个排序器来调整集合中 bean 的顺序。
 
 
 BeanComparator 是 BeanUtils API 中的一个类,使用它可以很简单地根
 
 据 bean 的属性对 Bean 类进行排序。
 
 
 需要说明的是这个比较器只是对符合 javabean 规范的类进行比较,如果类
 
 中没有这个属性或者属性没有 get 和 set 方法,那么在比较的时候就会抛出
 
 ClassCastException 。
 
 
 装饰比较器
 
 
 上边生成的比较器是带有一些默认的排序规则的,比如按着自然顺序排列,
 
 当遇到字符串的值是“”的时候就排列在前端。下边我将说明怎么改变这种默认
 
 的规则。
 
 
 为了完成这个任务,我们就需要使用 commons.collections.comparators
 
 提供的几个装饰类,ReverseComparator,NullComparator,
 
 FixedOrderComparator或者ComparatorUtils这个实用类。
 
 
 
 下边分别说明反序排列,允许空值排列和自定义顺序排列的实现方法。
 
 
 当我们想对让一个比较器按着反序进行排列的时候,可以使用如下的形
 
 式:
 
 
 comparator = new ReverseComparator(comparator);
 
 
 需要说明的是:这个功能的实现可以在排完序后对要排序的 array 或者
 
 list 调用其 reverse ()方法即可。但是这种做法并不适合下边谈到的对
 
 bean 的多字段排序时,而只对某一个字段逆序的情况。
 
 当对一个比较器进行特定顺序排列时需要用到FixedOrderComparator 。
 
 这个类用于定义一个特殊的顺序,对一组对象按照这样的自定义顺序进行排序。
 
 具体的事例如下:
 
 
 String[] severityOrder = { "Critical", "Minor", "Enhancement" };
 
 Comparator severityComparator = new FixedOrderComparator    (severityOrder);
 
 Comparator comparator=new BeanComparator("title",severityComparator) ;
 
 如上的程序便可以对 bean 的 title 属性按着数组中特定
 
 的顺序进行排序!
 
 最后需要说明的是,以上谈到的几个装饰在 ComparatorUtils 这个实用类中也提供了支持。
 
 具体使用如下:
 
 按着 bean 的属性为 null 时进行排序,可以选择属性为 null 时排在前边还是后边!
 
 ComparatorUtils.nullLowComparator(comparator);  或者 ComparatorUtils.nullHighComparator(comparator);
 
 当对一个排序器逆序时:
 
 ComparatorUtils.reversedComparator(mycmp); // 逆序
 
 
 
 多个属性的排序
 
 当我们想对 bean 的多个属性进行排序的时候,需要用到 commons.collections. ComparatorChain 。这个类 定义一组Comparator链,链中的Comparator对象会被依次执行。我们可以通过该类的 addComparator() 方法进行将当个的 comparator 对象加入到 comparator 链中,当使用的时候就可以和使用单个 comparator 一样。因为 comparatorChain 也继承了 comparator 的借口。当我们添加单个的 comparator 的时候,就可以利用上边谈到的对 comparator 进行装饰。
 
 ComparatorChain comparatorChain = new ComparatorChain( );
 
 comparatorChain.addComparator( new BeanComparator( "name" ) );
 
 comparatorChain.addComparator( new BeanComparator( "author" ) );
 
 comparaterChain.addComparator( new ReverseComparator                                                        (new BeanComparator("author") );
 
 具体使用的时候如下:
 
 Arrays.sort( books, comparatorChain );
 
 这个样子就可以将这个 comparator 传给 sort ()方法。当谈到对 bean 的多字段排序,而只对某一个字段逆序的情况时,可以参考如下的实现。
 
 ComparatorChain comparatorChain = new ComparatorChain( );
 
 comparatorChain.addComparator( new BeanComparator( "name" ) );
 
 这样子就可以实现了对 bean 的 name 按着正序排列而对 author 属性按着逆序排列。
 
 对组合 bean 进行排序
 
 当一个 bean 的某个属性是另外一个 java bean 的时候,而我们有想按着那个被组合进来 bean 的某个属性进行排序的时候,我们只需要很简单的将 BeanComparator 的参数设定成 bean.property 的形式,比如想对按着 book 的 author 中的 title 属性进行排序的时候就可以参考以下的形式:
 
 new BeanComparator
 
 ("author.title",severityComparator))
 
 Comparable 接口的实现
 
 最后如果想对 author 类实现 Comparable 接口可以参考如下的实现:
 
 public class Book implements Comparable {
 
 public int compareTo(Object arg0) {
 
 // comparators setup
 
 String[] severityOrder = { "Critical", "Major", "Minor", "Enhancement" };
 
 // 用于定义一个特殊的顺序,对一组对象按照这样的自定义顺序进行排序;
 
 Comparator severityComparator = new FixedOrderComparator(severityOrder);
 
 ComparatorChain compChain = new ComparatorChain();
 
 // 通过为属性指定一个已经存在的 Comparator ,而非采用默认的自然顺序
 
 compChain.addComparator(new BeanComparator("author.
 
 title", severityComparator));
 
 compChain.addComparator(new NullComparator
 
 (new BeanComparator("name"), true));
 
 compChain .addComparator(new ReverseComparator
 
 (new BeanComparator("id")));
 
 return compChain.compare(this, arg0);
 
 }
 
 }
 
 另外一个实现思路是:利用 commons.lang.compareBulder 实现。但是却失去了以上的装饰功能!
 | 
 |