java中对于复杂对象排序的模型及其实现 [转]

排序是编程中经常要碰到的问题,如果只是一般的数据库数据那么我们完全可以用数据sql语言来排序,但有的时候情况并不是这样,在一些特殊情况下我们不得不自己在java中写一些排序,而通常排序是一件让程序员非常恼火的事情,特别是那些可以让用户自由选择排序规则的情况,想想就头疼.今天正好公司一个组件就碰到了这样的情况,下面我说一下怎么来完成并且实现排序.

首先让我们来看一下用户需求是怎么样(为了更容易理解我将用户需求简化了一下,实际情况可能更复杂), 一个财务人员需要查询公司内所有用户的数据信息,对于查询出来的结果该用户能够自己定义排序规则(例如,他希望对用户姓名进行升序,同时对工资进行降序,并且对生日进行升序,也许有人会说这个直接用sql就能完成,请注意,这个用例是我简化了的,真实的情况会非常复杂,同时并不是一条sql就能解决的).

对于这个需求我们第一个想到的应该有一个员工信息对象(Employee),用户姓名,工资,生日都是这个对象的属性.用户的查询结果就是Employee对象的List.我们知道java本身提供了一个非常好的对于List的排序方法Collections.srot(List<T> 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 List<EmployeeOrder> orders;

    
public EmployeeSortOrder(List<EmployeeOrder> 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 List<Employee> employeeList;

    @Override
    
protected void setUp() throws Exception {
        
super.setUp();
        Employee e;
        Date date;
        Calendar cal
=Calendar.getInstance();
        employeeList
=new ArrayList<Employee>();
        
for (int i=0;i<10;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(){
        List
<EmployeeOrder> orders=new ArrayList<EmployeeOrder>();
        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);
        }

        
    }

    


    

}



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1753601

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值