您的位置:首页 > 编程语言 > Java开发

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

2012-03-19 23:51 357 查看
 

 

排序是编程中经常要碰到的问题,如果只是一般的数据库数据那么我们完全可以用数据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  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐