第12条: 考虑实现Comparable接口

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)前面两者是并且关系。

 

posted @ 2017-04-19 11:18  哀&RT  阅读(385)  评论(0编辑  收藏  举报