- 论坛徽章:
- 0
|
排序是编程中经常要碰到的问题,如果只是一般的数据库数据那么我们完全可以用数据sql语言来排序,但有的时候情况并不是这样,在一些特殊情况下我们不得不自己在java中写一些排序,而通常排序是一件让程序员非常恼火的事情,特别是那些可以让用户自由选择排序规则的情况,想想就头疼.今天正好公司一个组件就碰到了这样的情况,下面我说一下怎么来完成并且实现排序.
首先让我们来看一下用户需求是怎么样(为了更容易理解我将用户需求简化了一下,实际情况可能更复杂), 一个财务人员需要查询公司内所有用户的数据信息,对于查询出来的结果该用户能够自己定义排序规则(例如,他希望对用户姓名进行升序,同时对工资进行降序,并且对生日进行升序,也许有人会说这个直接用sql就能完成,请注意,这个用例是我简化了的,真实的情况会非常复杂,同时并不是一条sql就能解决的).
对于这个需求我们第一个想到的应该有一个员工信息对象(Employee),用户姓名,工资,生日都是这个对象的属性.用户的查询结果就是Employee对象的List.我们知道java本身提供了一个非常好的对于List的排序方法Collections.srot(
List
list,
Comparator
c),如果我们有一个针对Employee的Comparator对象他知道如何对两个Employee对象进行比较,根据比较结果来决定Employee对象的排列顺序,这样就能够实现用户的需求.第二点,用户能够自己定义一组排序规则,那么我们应该有一个EmployeeSortOrder对象,它包含了所有用户所定义的每一条规则,从需求理解我们可以知道这些规则就是对Employee对象中某些属性定义他的排序规则(升序或者降序),那么我们可以通过引入一个(EmployeeOrder)对象来指明具体Employee对象中有的属性如何来排序,这里需要包括这些属性的类型,应该对于不同的属性比较方式是不一样的.需求分析到这里我们基本就可以得到一个实现排序的模型.
![]()
下面我们来看一下具体代码:
Employee对象,一个标准的javabean对象,实际情况可能会是一个更加复杂的对象
![]()
![]()
/** *//**
![]()
*
![]()
*/
![]()
package com.demo.sort;
![]()
![]()
import java.math.BigDecimal;
![]()
import java.util.Date;
![]()
![]()
![]()
/** *//**
![]()
* @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 Auto-generated method stub
![]()
return super.hashCode();
![]()
}
![]()
![]()
@Override
![]()
![]()
public String toString() ...{
![]()
StringBuffer buf=new StringBuffer();
![]()
buf.append("[");
![]()
buf.append("employeeId="+employeeId).append(" ,");
![]()
buf.append("firstName="+firstName).append(" ,");
![]()
buf.append("lastName="+lastName).append(" ,");
![]()
buf.append("birthday="+birthday).append(" ,");
![]()
buf.append("payment="+payment);
![]()
buf.append("]");
![]()
return buf.toString();
![]()
}
![]()
![]()
![]()
![]()
}
![]()
Employee的complarator对象,他调用了ISortOrder来获得比较结果,这样我们就能够将具体的比较算法留到下层来实现,一旦Employe的比较规则改变,这个类也不需要在理会了.
![]()
![]()
/** *//**
![]()
*
![]()
*/
![]()
package com.demo.sort;
![]()
![]()
import java.util.Comparator;
![]()
![]()
![]()
/** *//**
![]()
* @author Administrator
![]()
*
![]()
*/
![]()
![]()
public class EmployeeComparator implements Comparator ...{
![]()
![]()
ISortOrder sortOrder;
![]()
![]()
![]()
public EmployeeComparator(ISortOrder sortOrder)...{
![]()
this.sortOrder=sortOrder;
![]()
}
![]()
![]()
/**//* (non-Javadoc)
![]()
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
![]()
*/
![]()
![]()
public int compare(Object arg0, Object arg1) ...{
![]()
return sortOrder.compare(arg0,arg1);
![]()
}
![]()
![]()
}
![]()
![]()
![]()
/** *//**
![]()
*
![]()
*/
![]()
package com.demo.sort;
![]()
![]()
![]()
/** *//**
![]()
* @author Administrator
![]()
*
![]()
*/
![]()
![]()
public interface ISortOrder ...{
![]()
![]()
public int compare(Object arg0, Object arg1);
![]()
![]()
}
![]()
具体的排序规则对象,这个对象记录了Employee对象中具体属性的排序规则和属性类型,如果用户定义了多条规则那么没一条规则就应该对于一个实例.
![]()
![]()
/** *//**
![]()
*
![]()
*/
![]()
package com.demo.sort;
![]()
![]()
![]()
/** *//**
![]()
* @author Administrator
![]()
*
![]()
*/
![]()
![]()
public class EmployeeOrder ...{
![]()
public final static int _LONG=0;
![]()
public final static int _STRING=1;
![]()
public final static int _DATE=2;
![]()
public final static int _BIGDECIMAL=3;
![]()
![]()
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的反射来获得具体属性值,并根据不同的属性类型进行比较,如果一共有3条比较规则,那么在比较2个Employee对象是先从第一个规则开始比较,如果比较出来一样,那么在进行第二个规则的比较,否则退出比较.由于本人很懒所以只对其中的一部分属性类型给出了比较方法,并没有实现所有数据类型的比较,大家可以自己实现,呵呵.
![]()
![]()
/** *//**
![]()
*
![]()
*/
![]()
package com.demo.sort;
![]()
![]()
import java.lang.reflect.Field;
![]()
import java.math.BigDecimal;
![]()
import java.util.List;
![]()
![]()
![]()
/** *//**
![]()
* @author Administrator
![]()
*
![]()
*/
![]()
![]()
public class EmployeeSortOrder implements ISortOrder ...{
![]()
![]()
private ListEmployeeOrder> orders;
![]()
![]()
![]()
public EmployeeSortOrder(ListEmployeeOrder> orders) ...{
![]()
this.orders = orders;
![]()
}
![]()
![]()
![]()
![]()
public int compare(Object arg0, Object arg1) ...{
![]()
int result = 0;
![]()
![]()
try ...{
![]()
Employee e1 = (Employee) arg0;
![]()
Employee e2 = (Employee) arg1;
![]()
![]()
for (EmployeeOrder order : orders) ...{
![]()
Object v1=getVaule(e1,order.getPropertyName());
![]()
Object v2=getVaule(e2,order.getPropertyName());
![]()
result=sort(v1,v2,order.getDataType());
![]()
![]()
if(!order.isAsc())...{
![]()
result*=-1;
![]()
}
![]()
![]()
if(result!=0)...{
![]()
break;
![]()
}
![]()
}
![]()
![]()
} catch (Exception e) ...{
![]()
// TODO: handle exception
![]()
}
![]()
return result;
![]()
}
![]()
![]()
![]()
private int sort(Object v1,Object v2,int dataType)...{
![]()
int result=0;
![]()
![]()
switch (dataType) ...{
![]()
case EmployeeOrder._STRING:
![]()
String s1=(String)v1;
![]()
String s2=(String)v2;
![]()
result=s1.compareTo(s2);
![]()
break;
![]()
case EmployeeOrder._BIGDECIMAL:
![]()
BigDecimal d1=(BigDecimal)v1;
![]()
BigDecimal d2=(BigDecimal)v2;
![]()
result=d1.compareTo(d2);
![]()
break;
![]()
case EmployeeOrder._LONG:
![]()
Long l1=(Long)v1;
![]()
Long l2=(Long)v2;
![]()
result=l1.compareTo(l2);
![]()
break;
![]()
default:
![]()
result=0;
![]()
break;
![]()
}
![]()
return result;
![]()
}
![]()
![]()
![]()
private Object getVaule(Object obj,String propertyName)...{
![]()
Object result=null;
![]()
![]()
try ...{
![]()
Class clazz = obj.getClass();
![]()
Field field = clazz.getDeclaredField(propertyName);
![]()
field.setAccessible(true);
![]()
result = field.get(obj);
![]()
![]()
} catch (Exception e) ...{
![]()
e.printStackTrace();
![]()
}
![]()
return result;
![]()
}
![]()
}
![]()
没多说的,测试类.
![]()
package com.demo.sort;
![]()
![]()
![]()
![]()
import java.math.BigDecimal;
![]()
import java.util.ArrayList;
![]()
import java.util.Calendar;
![]()
import java.util.Collections;
![]()
import java.util.Date;
![]()
import java.util.List;
![]()
![]()
import junit.framework.TestCase;
![]()
![]()
![]()
public class EmployeeSortTest extends TestCase...{
![]()
![]()
private ListEmployee> employeeList;
![]()
![]()
@Override
![]()
![]()
protected void setUp() throws Exception ...{
![]()
super.setUp();
![]()
Employee e;
![]()
Date date;
![]()
Calendar cal=Calendar.getInstance();
![]()
employeeList=new ArrayListEmployee>();
![]()
![]()
for (int i=0;i10;i++) ...{
![]()
e=new Employee();
![]()
if(0==i%3)
![]()
cal.add(Calendar.DATE, 1);
![]()
date=cal.getTime();
![]()
e.setBirthday(date);
![]()
e.setEmployeeId(Long.valueOf(i));
![]()
e.setFirstName("firstName"+i/2);
![]()
e.setLastName("LastName"+i*3);
![]()
e.setPayment(new BigDecimal(i%3));
![]()
employeeList.add(e);
![]()
}
![]()
}
![]()
![]()
@Override
![]()
![]()
protected void tearDown() throws Exception ...{
![]()
super.tearDown();
![]()
}
![]()
![]()
![]()
public void testSort()...{
![]()
ListEmployeeOrder> orders=new ArrayListEmployeeOrder>();
![]()
EmployeeOrder order=new EmployeeOrder("firstName",false,EmployeeOrder._STRING);
![]()
orders.add(order);
![]()
order=new EmployeeOrder("employeeId",false,EmployeeOrder._LONG);
![]()
orders.add(order);
![]()
ISortOrder sortOrder=new EmployeeSortOrder(orders);
![]()
EmployeeComparator comparator=new EmployeeComparator(sortOrder);
![]()
Collections.sort(employeeList,comparator);
![]()
![]()
for (Employee employee : employeeList) ...{
![]()
System.out.println(employee);
![]()
}
![]()
![]()
}
![]()
![]()
![]()
![]()
![]()
![]()
}
![]()
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/70940/showart_1090762.html |
|