今天有朋友问了下关于Comparator和Comparable的问题,很多人都曾经有过对这个问题的疑惑,今天把这个说明下.
Java 的 Comparators 和 Comparables 他们是什么?我们为什么要用他们?有一些读者也反应过这个问题。那么我们这篇文章将会详细讨论java.util.Comparator 和 java.lang.Comparable,并且会附上部分代码做更详细的阐述。
一个实现了comparable接口的对象的实例可以被用于和相同对象的不同实例做对比。它本身必须实现java.lang.Comparable的接口,这样它就拥有了对比的能力。
一个实现了comparator接口的对象能够对比不同的对象。它不能用于同一个类的不同实例的对比,但是可以用于其他的类的实例做对比。它必须实现java.util.Comparator的接口。
当有一个对象的列表的时候,在有些情况下你必须把这些对象按照不同的排序规则来排序。举例来说:考虑一个web页面需要显示职工的列表。通常情况下职工列表是按照职工的ID来排序。同样也可以根据姓名或者年龄来排序。在这些情况下有了这两个概念就会非常便于实现这个功能。
在Java中有两个接口来实现Comparable和Comparator,每一个对象都有一个必须实现的接口。分别是:
java.lang.Comparable: int compareTo(Object o1)
这个方法用于当前对象与o1对象做对比,返回int值,分别的意思是:
positive – 当前对象大于o1
zero – 当前对象等于o1
negative – 当前对象小于o1
java.util.Comparator: int compare(Object o1, Objecto2)
这个方法用于o1与o2对象做对比,返回int值,分别的意思是:
positive – o1大于o2
zero – o1等于o2
negative – o1小于o
java.util.Collections.sort(List)
和 java.util.Arrays.sort(Object[])
方法被用来排列使用内在排序(natural ordering)方式的对象。
java.util.Collections.sort(List, Comparator)
和 java.util.Arrays.sort(Object[], Comparator)
方法在Comparator如果可供比较的时候会被用到。
Employee的例子可以非常好的来解释这两个概念。首先我们写一个简单的Java bean来代表Employee。
public class Employee { private int empId; private String name; private int age; public Employee(int empId, String name, int age) { // set values on attributes } // getters & setters }
下面我们将使用一个工具类来构造一个Employees List,我们会对这个List处理不同的排序需求来演示。在下面的代码中Employees比较随意的被add到一个List中。
import java.util.*; public class Util { public static List<Employee> getEmployees() { List<Employee> col = new ArrayList<Employee>(); col.add(new Employee(5, "Frank", 28)); col.add(new Employee(1, "Jorge", 19)); col.add(new Employee(6, "Bill", 34)); col.add(new Employee(3, "Michel", 10)); col.add(new Employee(7, "Simpson", 8)); col.add(new Employee(4, "Clerk",16 )); col.add(new Employee(8, "Lee", 40)); col.add(new Employee(2, "Mark", 30)); return col; } }
职员的内在排序将根据Employee的id来排序。所以上面的Employee的类必须有可以对比的能力,如下面代码所示
public class Employee implements Comparable<Employee> { private int empId; private String name; private int age; /** * Compare a given Employee with this object. * If employee id of this object is * greater than the received object, * then this object is greater than the other. */ public int compareTo(Employee o) { return this.empId - o.empId ; } }
添加的compareTo()的方法为这个类的实例替换了默认的内在排序。所以如果是一个Employee对象的集合使用Collections.sort(List)来排序;排序会根据compareTo()方法里面定义的规则来完成。
我们接下来再写一个类来测试这个内在排序的机制。这个类使用Collections.sort(List)方法来对给定的List按照内在顺序来完成排序。
import java.util.*; public class TestEmployeeSort { public static void main(String[] args) { List coll = Util.getEmployees(); Collections.sort(coll); // sort method printList(coll); } private static void printList(List<Employee> list) { System.out.println("EmpId\tName\tAge"); for (Employee e: list) { System.out.println(e.getEmpId() + "\t" + e.getName() + "\t" + e.getAge()); } } }
执行下上面的代码,检查下输出结果。如下面所示:
EmpId Name Age
1 Jorge 19
2 Mark 30
3 Michel 10
4 Clerk 16
5 Frank 28
6 Bill 34
7 Simp 8
8 Lee 40
我们通过输出可以看到的是,这个列表是根据employee的id来完成的排序。因为employee的id是个int值,所以这些employee的实例就按照id从小到大的顺序完成了排序。