排序是编程中经常要碰到的问题如果只是一般的数据库数据那么我们完全可以用数据sql语言来排序但有的时候情况并不是这样在一些特殊情况下我们不得不自己在java中写一些排序而通常排序是一件让程序员非常恼火的事情特别是那些可以让用户自由选择排序规则的情况想想就头疼今天正好公司一个组件就碰到了这样的情况下面我说一下怎么来完成并且实现排序
首先让我们来看一下用户需求是怎么样(为了更容易理解我将用户需求简化了一下实际情况可能更复杂) 一个财务人员需要查询公司内所有用户的数据信息对于查询出来的结果该用户能够自己定义排序规则(例如他希望对用户姓名进行升序同时对工资进行降序并且对生日进行升序也许有人会说这个直接用sql就能完成请注意这个用例是我简化了的真实的情况会非常复杂同时并不是一条sql就能解决的)
对于这个需求我们第一个想到的应该有一个员工信息对象(Employee)用户姓名工资生日都是这个对象的属性用户的查询结果就是Employee对象的List我们知道java本身提供了一个非常好的对于List的排序方法Collectionssrot(List <T> list Comparator c ) 如果我们有一个针对Employee的Comparator对象他知道如何对两个Employee对象进行比较根据比较结果来决定Employee对象的排列顺序这样就能够实现用户的需求第二点用户能够自己定义一组排序规则那么我们应该有一个EmployeeSortOrder对象它包含了所有用户所定义的每一条规则从需求理解我们可以知道这些规则就是对Employee对象中某些属性定义他的排序规则(升序或者降序)那么我们可以通过引入一个(EmployeeOrder)对象来指明具体Employee对象中有的属性如何来排序这里需要包括这些属性的类型应该对于不同的属性比较方式是不一样的需求分析到这里我们基本就可以得到一个实现排序的模型
下面我们来看一下具体代码:
Employee对象一个标准的javabean对象实际情况可能会是一个更加复杂的对象
/** */ /**
*
*/
package comdemosort;
import javamathBigDecimal; import javautilDate;
/** */ /**
* @author Administrator
*
*/
public class Employee {
private Long employeeId;
private String firstName;
private String lastName;
private Date birthday;
private BigDecimal payment;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) { this birthday = birthday;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) { this employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) { this firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) { this lastName = lastName;
}
public BigDecimal getPayment() {
return payment;
}
public void setPayment(BigDecimal payment) { this payment = payment;
}
@Override
public int hashCode() {
// TODO Autogenerated method stub
return super hashCode();
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
bufappend( [ ); bufappend( employeeId= + employeeId)append( ); bufappend( firstName= + firstName)append( ); bufappend( lastName= + lastName)append( ); bufappend( birthday= + birthday)append( ); bufappend( payment= + payment); bufappend( ] ); return buftoString();
}
}
Employee的complarator对象他调用了ISortOrder来获得比较结果这样我们就能够将具体的比较算法留到下层来实现一旦Employe的比较规则改变这个类也不需要在理会了
/** */ /**
*
*/
package comdemosort;
import javautilComparator;
/** */ /**
* @author Administrator
*
*/
public class EmployeeComparator implements Comparator {
ISortOrder sortOrder;
public EmployeeComparator(ISortOrder sortOrder) { this sortOrder = sortOrder;
}
/**/ /* (nonJavadoc)
* @see javautilComparator#compare(javalangObject javalangObject)
*/
public int compare(Object arg Object arg) { return pare(argarg);
}
}
/** */ /**
*
*/
package comdemosort;
/** */ /**
* @author Administrator
*
*/
public interface ISortOrder {
public int compare(Object arg Object arg);
}
具体的排序规则对象这个对象记录了Employee对象中具体属性的排序规则和属性类型如果用户定义了多条规则那么没一条规则就应该对于一个实例
/** */ /**
*
*/
package comdemosort;
/** */ /**
* @author Administrator
*
*/
public class EmployeeOrder {
public final static int _LONG = ;
public final static int _STRING = ;
public final static int _DATE = ;
public final static int _BIGDECIMAL = ;
private String propertyName;
private boolean isAsc;
private int dataType;
public EmployeeOrder(String propertyName boolean isAsc int dataType) { this propertyName = propertyName; this isAsc = isAsc; this dataType = dataType;
}
public boolean isAsc() {
return isAsc;
}
public void setAsc( boolean isAsc) { this isAsc = isAsc;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) { this propertyName = propertyName;
}
public int getDataType() {
return dataType;
}
public void setDataType( int dataType) { this dataType = dataType;
}
}
这里是重点这个对象知道如何根据order规则来排序comparator就是调用这个对象的compare方法来获得比较结果由于 EmployeeOrder对象中定义了对象属性的排序方法所以这个对象中使用的java的反射来获得具体属性值并根据不同的属性类型进行比较如果一共有条比较规则那么在比较个Employee对象是先从第一个规则开始比较如果比较出来一样那么在进行第二个规则的比较否则退出比较由于本人很懒所以只对其中的一部分属性类型给出了比较方法并没有实现所有数据类型的比较大家可以自己实现呵呵
/** */ /**
*
*/
package comdemosort;
import javalangreflectField; import javamathBigDecimal; import javautilList;
/** */ /**
* @author Administrator
*
*/
public class EmployeeSortOrder implements ISortOrder {
private List < EmployeeOrder > orders;
public EmployeeSortOrder(List < EmployeeOrder > orders) { this orders = orders;
}
public int compare(Object arg Object arg) {
int result = ;
try {
Employee e = (Employee) arg;
Employee e = (Employee) arg;
for (EmployeeOrder order : orders) { Object v = getVaule(eordergetPropertyName()); Object v = getVaule(eordergetPropertyName()); result = sort(vvordergetDataType()); if ( ! orderisAsc()) {
result *= ;
}
if (result != ) {
break ;
}
}
} catch (Exception e) {
// TODO: handle exception
}
return result;
}
private int sort(Object vObject v int dataType) {
int result = ;
switch (dataType) { case EmployeeOrder_STRING:
String s = (String)v;
String s = (String)v;
result = pareTo(s);
break ;
case EmployeeOrder_BIGDECIMAL:
BigDecimal d = (BigDecimal)v;
BigDecimal d = (BigDecimal)v;
result = pareTo(d);
break ;
case EmployeeOrder_LONG:
Long l = (Long)v;
Long l = (Long)v;
result = pareTo(l);
break ;
default :
result = ;
break ;
}
return result;
}
private Object getVaule(Object objString propertyName) {
Object result = null ;
try { Class clazz = objgetClass(); Field field = clazzgetDeclaredField(propertyName); fieldsetAccessible( true ); result = fieldget(obj); } catch (Exception e) { eprintStackTrace();
}
return result;
}
}
没多说的测试类
package comdemosort;
import javamathBigDecimal; import javautilArrayList; import javautilCalendar; import javautilCollections; import javautilDate; import javautilList;
import junitframeworkTestCase;
public class EmployeeSortTest extends TestCase {
private List < Employee > employeeList;
@Override
protected void setUp() throws Exception { super setUp();
Employee e;
Date date;
Calendar cal = CalendargetInstance();
employeeList = new ArrayList < Employee > ();
for ( int i = ;i < ;i ++ ) {
e = new Employee();
if ( == i % )
caladd(CalendarDATE ); date = calgetTime(); esetBirthday(date); esetEmployeeId(LongvalueOf(i)); esetFirstName( firstName + i / ); esetLastName( LastName + i * ); esetPayment( new BigDecimal(i % )); employeeListadd(e);
}
}
@Override
protected void tearDown() throws Exception { super tearDown();
}
public void testSort() {
List < EmployeeOrder > orders = new ArrayList < EmployeeOrder > ();
EmployeeOrder order = new EmployeeOrder( firstName false EmployeeOrder_STRING); ordersadd(order); order = new EmployeeOrder( employeeId false EmployeeOrder_LONG); ordersadd(order);
ISortOrder sortOrder = new EmployeeSortOrder(orders);
EmployeeComparator comparator = new EmployeeComparator(sortOrder);
Collectionssort(employeeListcomparator); for (Employee employee : employeeList) { Systemoutprintln(employee);
}
}
}