关于排序
众所周知,如果需要在
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
实现。但是却失去了以上的装饰功能!
最后需要说明的是,由于我在工作中最近用到这些排序,所以整理了一下,希望对您有用。同时参考了很多网上的资料,谢!
事例代码我放到了:
commons2006@126.com
,
密码是
commons2006
posted on 2006-09-16 16:33
张氏兄弟 阅读(1155)
评论(1) 编辑 收藏