在进行java开发时,经常需要对list进行排序,本文对此进行小结。总结了两种方法,第一种是通过原生支持的Comparator做排序,第二种是通过apache-common的工具包进行排序。相比而言,第二种代码可读性、易用性更强,推荐使用第二种。
一、排序目标
我们要对User类组成的list进行排序,先按年龄age倒序排,再按等级grade正序排,如果grade为null,视为最大值,要排在最后。
1.User类
public class User{
private int age ;
private String grade ;
public int getAge() {
return age ;
}
public void setAge(int age) {
this.age = age;
}
public String getGrade() {
return grade ;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
2.初始化测试数据
User user1 = new User();
user1.setAge(15);
user1.setGrade( "A");
users.add(user1);
User user2 = new User();
user2.setAge(16);
user2.setGrade( "A");
users.add(user2);
User user3 = new User();
user3.setAge(15);
user3.setGrade( null);
users.add(user3);
二、通过Comparator做排序
主要是实现Comparator方法,代码如下
Collections. sort(users, new Comparator<Object>(){
@Override
public int compare(Object arg1, Object arg2) {
User u1 = (User)arg1;
User u2 = (User)arg2;
if(u2.getAge() == u1.getAge())
{
if(u2.getGrade() == null || u1.getGrade() == null)
{
if(u2.getGrade() == null)
{
return -1;
}
else
{
return 1;
}
}
return u1.getGrade().compareTo(u2.getGrade());
}
return u2.getAge() - u1.getAge();
};
});
代码贴完,再来细说。这段代码实在不忍直视,可读性比较差。首先,为了实现主次排序的需求,需要在if(u2.getAge() == u1.getAge())时,再对grade进行判断,这就多了一层if嵌套。判断grade大小前,还需要对grade是否为null做判断,又多了一个if。其次,再看compare方法的返回值是怎么定义的:如果是正序排序,则当compare方法的参数1(arg1)大于参数2(arg2)时,需返回正数,如果相等,则返回0;逆排则相反,arg1大于arg2时,需返回负数。这个规则不方便记。那么,有没有更好的方法,答案是有的,可以借助apache-common的包。
三、通过apache-common工具包进行排序
1.首先需要引入Apache-common的beanutils、collections、logging三个包
2.代码示例如下
Comparator mycmp1 = ComparableComparator.getInstance ();
mycmp1 = ComparatorUtils. reversedComparator(mycmp1); //逆序
Comparator mycmp2 = ComparableComparator.getInstance ();
mycmp2 = ComparatorUtils. nullHighComparator(mycmp2); //允许null
// 声明要排序的对象的属性,并指明所使用的排序规则,如果不指明,则用默认排序
ArrayList<Object> sortFields = new ArrayList<Object>();
sortFields.add( new BeanComparator("age" , mycmp1)); //主排序(第一排序)
sortFields.add( new BeanComparator("grade" , mycmp2)); //次排序(第二排序)
// 创建一个排序链
ComparatorChain multiSort = new ComparatorChain(sortFields);
// 开始真正的排序,按照先主,后副的规则
Collections.sort (users , multiSort);
3.说明
其实大家看代码应该就能明白了,这里再啰嗦几句,看工具包是如何减轻程序员压力的
首先,通过ComparatorUtils封装好的排序器,可以直接声明是要倒序排,还是正序排(默认是正序,不需要声明),而不需再考虑Comparator返回值。
其次,通过ComparatorChain排序链的先后添加顺序,可以很方便地定义第一排序、第二排序甚至是第九百九十九排序……
最后,通过BeanComparator,直接传参为要排序的字段名称,代码可读性很强,之后要替换也很方便。假设要将age替换成别的排序字段,在第一种排序方法中,至少要替换四个地方,而在这里,替换一个地方即可。