java对象排序

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);
        }

        
    }

    


    

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值