CompareTo方法没有在Object中声明,它是Comparable接口中的唯一的方法,不但允许进行简单的等同性比较,而且允许执行顺序比较。类实现了Comparable接口,就表明它的实例具有内在的排序关系。为实现Comparable接口的对象排序就这么简单:Arrays.sort(a);
实现Comparable好处在于:一旦实现了Comparable接口,它可以跟许多泛型算法以及依赖于该接口的集合实现进行协作,只需付出很小的努力就可以获得非常强大的功能。
Java平台的所有值类都实现了Comparable接口。如果一个类具有明显的内在排序关系,比如按字母顺序,按数字顺序,按年代顺序,就应该实现这个接口。
CompareTo方法的通用约定:
将这个对象与指定的对象进行比较。当该对象小于、等于、大于指定对象的时候,分别返回一个负整数、零或者正整数。如果由于指定对象的类型而无法与该对象进行比较,则抛出ClassCastException异常。
如何很好的实现Comparable接口,根据CompareTo方法的通用约定我们可以总结出以下四点:
(1)满足对称性。
即对象A.comparaTo(B) 大于0的话,则B.comparaTo(A)必须小于0;
(2)满足传递性。
即对象A.comparaTo(B) 大于0,对象B.comparaTo(Z)大于0,则对象A.comparaTo(Z)一定要大于0;
(3)建议comparaTo方法和equals()方法保持一致。
即对象A.comparaTo(B)等于0,则建议A.equals(B)等于true。
(4)对于实现了Comparable接口的类,尽量不要继承它,而是采取复合的方式。
(5)一个建议,考虑BigDecimal类,它的compareTo方法和equals不一致,如果创建HashSet实例,并添加new BigDecimal("1.0") 和 new BigDecimal("1.00"),这个集合就将包含两个元素,因为HashSet通过equals比较是不相等的,然而,使用TreeSet来执行同样的过程,集合只包含一个元素,因为它是通过compareTo方法进行比较的。下面看下简单的comparTo例子:
public class Person implements Comparable<Person>{ private String name; private int age; private char sex; public Person(){} public Person(String name, int age, char sex) { this.name = name; this.age = age; this.sex = sex; } //String Integer等实现了Comparable,所以字符串这些比较可以用它们重写的方法compareTo(),如“abc”.compareTo(“bcd”);会返回正反表示大小,0为相等 public int compareTo(Person o) { //比较名字 if(o.getName() == null || this.name == null){ return -1; } return this.name.compareTo(o.getName()); //升序 //按照年龄排序 //return this.age - o.getAge(); //升序 } public String toString(){ return this.name +"---"+this.age; } //getter、setter方法... }
public static void main(String[] args) { //根据姓名排序 List<Person> list = new ArrayList<Person>();//初始化一个list list.add(new Person("b", 11, 'M')); list.add(new Person("a", 10, 'M')); list.add(new Person("c", 12, 'W')); Collections.sort(list); //集合排序,就是这么简单 System.out.println(list); //根据age排序 //将注释return this.age - o.getAge();去掉,把上面的注释掉 Person[] array = new Person[]{new Person("aa", 21, 'M'),new Person("c", 11, 'M'),new Person("d", 31, 'M')};//初始化一个数组 Arrays.sort(array); //数组排序,就是这么简单 System.out.println(Arrays.toString(array)); }
好了,上面的comparable例子很简单吧。
总结:什么时候应该考虑实现Comparable接口
(1)你写的类是一个值类(前面的文章介绍过)。
(2)类中有很明显的内在排序关系,如字母排序、按数值顺序或是时间等。
(3)前面两者是并且关系。