Java如何实现复杂对象的排序

原创|其它|编辑:郝浩|2009-10-27 13:39:32.000|阅读 826 次

概述:排序是编程中经常要碰到的问题,如果只是一般的数据库数据那么我们完全可以用数据sql语言来排序,但有的时候情况并不是这样,在一些特殊情况下我们不得不自己在java中写一些排序.

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

  排序是编程中经常要碰到的问题,如果只是一般的数据库数据那么我们完全可以用数据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 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);
  }
  }
  }


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:IT专家网

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP