排序—对象类排序之Comparator接口

WHY:当需要对某个类进行排序,但是这个类本身并不支持排序时,可以用到比较器,java中定义了两种比较器的类型,第一种是comparator可用于数组或者集合的排序,第二种是comparable可用于数组的排序。

首先来讲一下comparator比较器

场景1

需要对单位的员工信息列表进行排序,要求如下:

1、级别高的排在前面

2、同级别的,工资高的排在前面

3、同工资的,资历老的排在前面

STEP ONE:创建Employee类

public class Employee implements Serializable {

	private static final long serialVersionUID = 4775629632953317597L;
	public int id;
	public int level;
	public int salary;
	public int year;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getLevel() {
		return level;
	}
	public void setLevel(int level) {
		this.level = level;
	}
	public int getSalary() {
		return salary;
	}
	public void setSalary(int salary) {
		this.salary = salary;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	public Employee(int id, int level, int salary, int year) {
		this.id = id;
		this.level = level;
		this.salary = salary;
		this.year = year;
	}
}

STEP TWO:创建Comparator比较器

public class EmpComparator implements Comparator<Employee> {  
	  
    @Override  
    public int compare(Employee employee1, Employee employee2) {  
          int cr = 0;  
          //按级别降序排列  
          int a = employee2.getLevel() - employee1.getLevel();  
          if (a != 0) {  
              cr = (a > 0) ? 3 : -1;  
          } else {  
              //按薪水降序排列  
              a = employee2.getSalary() - employee1.getSalary();  
              if (a != 0) {  
                  cr = (a > 0) ? 2 : -2;  
              } else {  
                  //按入职年数降序排列  
                  a = employee2.getYear() - employee1.getYear();  
                  if (a != 0) {  
                      cr = (a > 0) ? 1 : -3;  
                  }  
              }  
          }  
          return cr;  
    }  
}  

STEP THREE:创建单元测试主类,测试排序结果

public class SortTest {  
 
    public static void main(String[] args) {  
        List<Employee> employeeList = new ArrayList<Employee>() {  
            {  
                add(new Employee(1, 9, 10000, 10));  
                add(new Employee(2, 9, 12000, 7));  
                add(new Employee(3, 5, 10000, 12));  
                add(new Employee(4, 5, 10000, 6));  
                add(new Employee(5, 3, 5000, 3));  
                add(new Employee(6, 1, 2500, 1));  
                add(new Employee(7, 5, 8000, 10));  
                add(new Employee(8, 3, 8000, 2));  
                add(new Employee(9, 1, 3000, 5));  
                add(new Employee(10, 1, 2500, 4));  
                add(new Employee(11, 2, 2000, 4));  
            }  
        };  
        Collections.sort(employeeList, new EmpComparator());  
        System.out.println("ID\tLevel\tSalary\tYears");  
        System.out.println("=============================");  
        for (Employee employee : employeeList) {  
            System.out.printf("%d\t%d\t%d\t%d\n", employee.getId(), employee.getLevel(), employee.getSalary(),  employee.getYear());  
            }  
        System.out.println("=============================");  
    }  
}  

以上代码就完整的演示了使用比较器接口Comparator,对本身不支持排序的实体类进行排序的整个过程,接着我们来介绍一下java.util.Comparator接口的工作原理:

Comparator接口的源代码是:

public interface Comparator{

int compare(T o1,T o2);

boolean equals(Object obj) ;

}

当一个类要实现Comparator接口时,它必须要实现compare函数,而equals函数则可以不实现

本身的话,int compare(T o1,To2)函数是比较o1,o2的大小,

如果返回负值则意味着o1比o2小;否则o1等于o2;返回正值则意味着o1比o2大

但是在Comparator的实现类中要重写compare方法

在Comparator比较器中升降序可以理解为:

如果o1比o2大,若返回重写后的compare方法返回的是正数,此时调用的函数Collection.sort()就是升序,若返回的是负数,此时调用的函数Collection.sort()就是降序

同理如果o1比o2小,若返回的是负数,此时调用的函数Collection.sort()就是升序,若返回的是正数,此时调用的函数Collection.sort()就是降序

总结一句就是说,重写后的compare方法,返回的值若与compare(T o1,T o2)函数同正负号则是升序排列,若正负号相反则降序排列

public class EmpComparator implments Comparator<Employee>{
public int compare(Employee e1,Employee e2){
if(e1.getLevel()>e2.getLevel())
{return -1;}
}
}

像如上所示的代码,e1的级别大于e2的级别,但是在Comparator接口的实现类EmpComparator的重写的compare方法中却返回的是负数,因此EmpComparator实现的是雇员按照级别降序排列

场景2

java的比较器有两类,一种是comparator在场景一中已经详细描述了,另一种是comparable接口,我们现在来讲第二种。

先说一下为什么有两种比较器呢,我们先来看一下comparable接口是如何工作的:

让需要排序的类实现comparable接口,在其中重写compareTo(T  o)方法,并在其中定义排序规则,就可以直接用java.util.Arrays.util来排列对象

用comparable的好处在于,直接在对象中就定义了排序的规则,不用再重新重新写比较器的实现类

    class Student implements Comparable<Student>{  
        private String name;  
        private int age;  
        private float score;  
          
        public Student(String name, int age, float score) {  
            this.name = name;  
            this.age = age;  
            this.score = score;  
        }  
          
        public String toString()  
        {  
            return name+"\t\t"+age+"\t\t"+score;  
        }  
      
        @Override  
        public int compareTo(Student o) {  
            // TODO Auto-generated method stub  
            if(this.score>o.score)//score是private的,为什么能够直接调用,这是因为在Student类内部  
                return -1;//由高到底排序  
            else if(this.score<o.score)  
                return 1;  
            else{  
                if(this.age>o.age)  
                    return 1;//由底到高排序  
                else if(this.age<o.age)  
                    return -1;  
                else  
                    return 0;  
            }  
        }  
    }  
      
    public class ComparableDemo01 {  
      
        /** 
         * @param args 
         */  
        public static void main(String[] args) {  
            // TODO Auto-generated method stub  
            Student stu[]={new Student("zhangsan",20,90.0f),  
                    new Student("lisi",22,90.0f),  
                    new Student("wangwu",20,99.0f),  
                    new Student("sunliu",22,100.0f)};  
            java.util.Arrays.sort(stu);  
            for(Student s:stu)  
            {  
                System.out.println(s);  
            }  
        }  
    }  

看完了comparable比较器之后我们来说一下为什么有两种比较器:

因为有些类在设计的时候没有考虑让其实现comparable接口,因此才有了comparator比较器用以补救。

场景3

我们看到,需要排列的对象,有时候是装在数组里,有时候是装在集合里,相应的也就需要调用不同的排序方法,

当对象装在数组中时

如果是用的comparator比较器,则调用Arrays.sort()方法,需要传递两个参数,(数组名  new EmpComparator())

如果用的是comparable比较器,则调用Arrays.sort()方法,需要传递一个参数,(数组名)

当对象装在集合中时

则只能调用Collection.sort()方法,需要传递两个参数(集合名  new EmpComparator()),即对象和比较器,这也就意味着集合只能用comparator比较器来实现对象的排序。




猜你喜欢

转载自blog.csdn.net/qll19970326/article/details/80042686