java排序总结(Comparator、apache-common工具包两种方法)

 在进行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(){

	  @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 sortFields = new ArrayList();
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替换成别的排序字段,在第一种排序方法中,至少要替换四个地方,而在这里,替换一个地方即可。

你可能感兴趣的:(JAVA)