java 中Comparable 和 Comparator比较

Comparable 和 Comparator比较

  • 两者都 是接口
  • Comparable
    • 继承了这个接口,实现接口的方法(自定义排序规则),就表示“该类支持排序”
    • 相当于“内部比较”
    • 如果某个类实现了这个接口,就可以通过 Arrasys.sort() 对该类的数组排序
    • 如果这个类装在容器中(List,Set),就可以用Collections.sort()排序
  • Comparato
    • 是比较器的意思,器 相当于工具 ,某个类实现这个接口就可以有比较的规则
    • 相当于“外部比较”

a.Comparable 接口

例子**

/**
 * @author bigguy_hc
 * @create 2018-09-03 11:32
 */
public class Person implements Comparable<Person>{  // 实现接口,重写方法
    int age;
    int score;

    public Person(){}

    public Person(int age,int score){
        this.age = age;
        this.score = score;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", score=" + score +
                '}';
    }

    @Override
    // 重写方法,自定义排序规则,这里表示按年龄排序,
    public int compareTo(com.bigguy.Person o) {     
        return this.getAge()-o.getAge();
    }
}

测试 Arrays.sort()

// 数组排序 
public void test2(){

        Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};

 // 内部判断的依据是实现了 Comparable 接口,排序规则是 Person 重写compareTo()方法定义的规则

        Arrays.sort(pers);         
        for (Person per : pers) {
            System.out.println(per);
        }
    }

输出

Person{age=21, score=85}
Person{age=23, score=91}
Person{age=24, score=100}

测试 Collections.sort()

public void test2(){

        Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};

        List list = Arrays.asList(pers);

        Collections.sort(list);             // 内部的比较规则是内部原始的 compareTo()方法

        for (Person person : list) {
            System.out.println(person);
        }
    }

输出

Person{age=21, score=85}
Person{age=23, score=91}
Person{age=24, score=100}

b.Comparator接口

如果就按照上面的代码(person 实现了Comparable 接口并重写了对应的方法)

此时,需求改变,现在需要通过 score 从大到小排序,不更改 person 原来代码,就需要自定义比较器类

class PersonScoreComparator implements Comparator{
    public int compare(Person o1, Person o2) {
        return o2.getScore()-o1.getScore();
    }
}

 public void testComparator(){

     Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};

     List list = Arrays.asList(pers);

     // 这里传入一个比较器,里面自定义了排序规则
     Collections.sort(list,new PersonScoreComparator());

     for (Person person : list) {
         System.out.println(person);
     }
 }
/*输出:
    Person{age=24, score=100}
    Person{age=23, score=91}
    Person{age=21, score=85}
*/
注意:
    至于什么时候是升序,什么时候是降序,就是重写方法时的规则:

    public int compare(Person o1, Person o2) {
        return o2.getScore()-o1.getScore();     // 用 o2 - o1 的就是 大 -> 小
    }

c.总结

Comparator 的灵活性更高,不修改比较累的原代码,可以自定义类并重写方法,但是比较麻烦,

Comparable 简单,灵活性差,如果需要改变,需要更改原代码

d. Arrays.sort() 和 Collections.sort() 的 jdk 源码

Arrays.sort()

public static void sort(Object[] a) {
    if (LegacyMergeSort.userRequested)
        legacyMergeSort(a);
    else
        ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}

Collections.sort() 没有传入比较器

 public static super T>> void sort(List list) {
     list.sort(null);       // 传入 null 表示传入的比较器为 null
 }

default void sort(Comparatorsuper E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

public static  void sort(T[] a, Comparatorsuper T> c) {
    if (c == null) {        // 因为上面传入 null ,所以走 sort(a)
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, 0, a.length, c, null, 0, 0);
    }
}

Collections.sort() 传入比较器

 public static  void sort(List list, Comparatorsuper T> c) {
     list.sort(c);
 }
// 这个方法其实是和上面方法时同一个方法,提高了代码的复用性 
default void sort(Comparatorsuper E> c) {    
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

总结:

Arrays.sort() 和 Collections.sort() 先判断是否传入比较器

如果传入比较器按比较器的规则比较

否则如果实现了Comparable 接口,按照重写 的compareTo()方法规则比较

否则,如果还比较则报错(里面的元素没有比较性)

你可能感兴趣的:(Java,SE)