3.多列排序问题
3.1排序条件的数量
我们知道,SQL语句能够实现强大的排序功能,能够按照不同字段的排列进行排序,也能够按照升序,降序排序。比如下面的语句。 order by field1 asc, field2 asc, field3 desc。
这个排序条件按照field1的升序,field2的升序,field3的降序排序。 注意,排在前面的字段具有较高的优先级。 比如,两条纪录A和B,满足如下条件: (1)A.field1 > B.field1,(2)A.field2 < B.field2。 这时如果按照order by field1, field2语句排序,那么 A > B。 如果上述条件中的(1)A.field1 > B.field1变化为A.field1 == B.field1。这时,条件(2)就会起作用。这时,A < B。
我们来看看在Java中如何实现这种灵活而强大的排序。 我们还是以上一节的Record类为例。Record类有3个字段,我们来看一看,有多少种可能的排序条件。 (1)按field1排序。(2)按field2排序。(3)按field3排序。(4)按field1,field2排序。(5)按field1升序,按field2降序排序…...
各种排序条件的排列组合,大概共有30种。而且,随着字段个数的增长,排序条件的个数呈幂级数的增长。 按照上一节的sort和Comparator方法,如果我们需要达到按照任意条件进行排序的目的,那么我们需要为每一个排序条件提供一个Comparator,我们需要30个Comparator类。:-)
当然,我们不会这么做,我们能够进一步提取这个问题中的相同重复部分,优化我们的解决方案。
3.2 问题分析 我们来分析这个问题中变化的部分和不变的部分。 上面所有的排序条件中,不变的部分有3部分: (1)A.field1和B.field1的比较, (2)A.field2和B.field2的比较, (3)A.field3和B.field3的比较;
变化的部分有两部分, (1)这三种比较条件的任意组合排列, (2)升序和降序。
根据这段分析,我们引入两个类,ReverseComparator类和CompositeComparator类。 CompositeComparator类用来解决字段的组合排列问题。 ReverseComparator类用来解决字段的升序、降序问题。
3.3 ReverseComparator类的代码
import java.util.Comparator;
public class ReverseComparator implements Comparator{ /** the original comparator*/ private Comparator originalComparator = null;
/** constructor takes a comparator as parameter */ public ReverseComparator(Comparator comparator){ originalComparator = comparator; }
/** reverse the result of the original comparator */ public int compare(Object o1, Object o2){ return - originalComparator.compare(o1, o2); } }
|
3.4 CompositeComparator类的代码
import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.LinkedList;
public class CompositeComparator implements Comparator{ /** in the condition list, comparators' priority decrease from head to tail */ private List comparators = new LinkedList();
/** get the comparators, you can manipulate it as need.*/ public List getComparators(){ return comparators; }
/** add a batch of comparators to the condition list */ public void addComparators(Comparator[] comparatorArray){ if(comparatorArray == null){ return; }
for(int i = 0; i < comparatorArray.length; i++){ comparators.add(comparatorArray[i]); } }
/** compare by the priority */ public int compare(Object o1, Object o2){ for(Iterator iterator = comparators.iterator(); iterator.hasNext();){ Comparator comparator = (Comparator)iterator.next();
int result = comparator.compare(o1, o2);
if(result != 0){ return result; } }
return 0; } }
|
3.5 Comparator的组合应用 这一节讲述上面两个类的用法。 对应前面的排序问题,我们只需要3个Comparator类: (1)Field1Comaprator; (2)Field2Comaprator; (3)Field3Comaprator。
下面举例说明,如何组合这些Comparator实现不同的排序条件。 (1)order by field1, field2
CompoiComparator myComparator = new CompoiComparator(); myComparator. addComparators( new Comparator[]{ new Field1Comaprator (), new Field2Comaprator ()}; );
// records is a list of Record Collections.sort(records, myComparator); (1)order by field1 desc, field2
CompoiComparator myComparator = new CompoiComparator(); myComparator. addComparators( new Comparator[]{ new ReverseComparator(new Field1Comaprator ()), new Field2Comaprator ()}; );
// records is a list of Record Collections.sort(records, myComparator);
|
这里提供的ReverseComparator类和CompositeComparator类都采用了Decorator Pattern。 CompositeComparator类同时也是Composite Pattern。
4.过滤条件的排列组合 过滤条件问题也属于条件组合问题的范畴。比如JDK提供的java.io.File类提供了一个文件过滤方法listFile(FileFilter),用户可以定制不同的FileFilter,实现不同的过滤条件,比如文件时间在某个范围内;文件后缀名,文件名符合某种模式;是目录,还是文件,等等。 同样,我们可以应用上述的解决方法,实现灵活的过滤条件组合――用一个CompositeFilter类任意组合过滤条件,用一个ReverseFilter类作为排除条件。
4.1 CompositeFilter类的代码
import java.io.FileFilter; import java.io.File;
import java.util.Iterator; import java.util.List; import java.util.LinkedList;
public class CompositeFilter implements FileFilter {
/** in the filter list, every condition should be met. */ private List filters = new LinkedList();
/** get the filters, you can manipulate it as need.*/ public List getFilters(){ return filters; }
/** add a batch of filters to the condition list */ public void addComparators(FileFilter[] filterArray){ if(filterArray == null){ return; }
for(int i = 0; i < filterArray.length; i++){ filters.add(filterArray[i]); } }
/** must meet all the filter condition */ public boolean accept(File pathname) { for(Iterator iterator = filters.iterator(); iterator.hasNext();){ FileFilter filter = (FileFilter)iterator.next();
boolean result = filter.accept(pathname);
// if any condition can not be met, return false. if(result == false){ return false; } }
// all conditions are met, return true. return true; } }
|
4.2 ReverseFilter类的代码
import java.util.Comparator;
public class ReverseComparator implements Comparator{ /** the original comparator*/ private Comparator originalComparator = null;
/** constructor takes a comparator as parameter */ public ReverseComparator(Comparator comparator){ originalComparator = comparator; }
/** reverse the result of the original comparator */ public int compare(Object o1, Object o2){ return - originalComparator.compare(o1, o2); } }
|
|
|