Comparable接口与Comparator接口

Comparable接口与Comparator接口

关于如何比较两个对象的大小问题,JDK提供了两个接口java.lang.Comparablejava.util.Comparator

自然排序:java.lang.Comparable

Comparable接口只提供了一个方法:

<pre> public interface Comparable<T> { public int compareTo(T o); } </pre>

该接口的返回值是int:如果是正数,表示当前对象比o大;如果是负数,表示当前对象小于o;如果为0,表示两者相等。

下面是一个实现了Comparable接口的Employee类,及测试代码

<pre> package com.company.employee; public class Employee implements Comparable<Employee> { private int empId; private String name; private int age; public Employee(int empId, String name, int age) { this.empId = empId; this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public int getEmpId() { return empId; } /** * 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; } } package com.company.employee; import java.util.ArrayList; import java.util.List; 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; } } package com.company.employee; import java.util.Collections; import java.util.List; 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()); } } } </pre>

实现了java.lang.Comparable接口后,就可以使用java.util.Collections.sort(List)java.util.Arrays.sort(Object[])这两个方法来对一组对象(列表或数组)来进行排序,如上面的例子中所示。调用sort方法进行排序时,在比较两个对象的大小时,就会调用对象的CompareTo方法来进行判断。上面的例子中,就会按照属性empId进行排序。

比较器排序:java.util.Comparator

但上面的实现有个问题:由于比较策略与类绑定了,因此我们只能按照属性empId来对Employee对象来进行排序。如果要使用其他属性来进行排序,那我们就不得不修改Employee类中的compareTo方法。但无论怎样,我们都只能有一种排序规则。此时,比较器Comparator就起作用了。

实现Comparator接口只需要实现其中的compare方法:

<pre> int compare(T o1, T o2); </pre>

通过实现一个比较器类Comparator,我们在不更改原类(Employee)的前提下,就可以按照不同的规则来进行比较。如按照名字进行比较的示例代码如下

<pre> package com.company.employee; import java.util.Comparator; public class EmpSortByName implements Comparator<Employee> { public int compare(Employee o1, Employee o2) { return o1.getName().compareTo(o2.getName()); } } package com.company.employee; import java.util.Collections; import java.util.List; public class TestEmployeeSort { public static void main(String[] args) { List coll = Util.getEmployees(); // Collections.sort(coll); // sort method Collections.sort(coll, new EmpSortByName()); 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()); } } } </pre>

如上代码所示,我们可以传递一个比较器对象给sort方法,在比较两个对象的大小时,sort方法就会调用比较器对象的compare()方法来进行比较。

总结

  1. Comparable接口位于java.lang包下,Comparator接口位于java.util包下
  2. Comparable将比较代码(规则)嵌入在类自身的代码中,只提供一种规则。Comparator是一个比较器,可以在另一个独立的类中定义比较规则,可以通过提供多个比较器类提供多种比较规则
  3. 如果无法修改原类,又想要实现排序,则只能提供额外的比较器对象Comparator
  4. 实现了Comparable接口,可以调用java.util.Collections.sort(List)java.util.Arrays.sort(Object[])这两个方法来进行排序;通过提供Comparator对象,可以调用java.util.Collections.sort(List<T> list, Comparator<? super T> c)java.util.Arrays.sort(T[] a, Comparator<? super T> c)来进行排序

猜你喜欢

转载自my.oschina.net/u/2561528/blog/1821258