Comparable和Comparator比較

Comparable定義:
  • Comparable是一個(gè)排序接口,當(dāng)一個(gè)類(lèi)實(shí)現(xiàn)了該接口,就意味著“該類(lèi)支持排序”。

具體實(shí)現(xiàn):

package java.lang;
import java.util.*;
public interface Comparable<T> {
    public int compareTo(T o);
}

我們可以看到它是通過(guò)compareTo方法來(lái)進(jìn)行排序的。

假設(shè)我們通過(guò) x.compareTo(y) 來(lái)“比較x和y的大小”。
若返回“負(fù)數(shù)”,意味著“x比y小”;返回“零”,意味著“x等于y”;返回“正數(shù)”,意味著“x大于y”。

Comparator定義:
  • Comparator為比較器接口,若要實(shí)現(xiàn)某個(gè)本身不支持排序的類(lèi),可以通過(guò)定義定義一個(gè)Comparator接口來(lái)實(shí)現(xiàn)類(lèi)的排序。

具體實(shí)現(xiàn):

package java.util;
public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
  • 若一個(gè)類(lèi)要實(shí)現(xiàn)Comparator接口:它一定要實(shí)現(xiàn)compareTo(T o1, T o2) 函數(shù),但可以不實(shí)現(xiàn) equals(Object obj) 函數(shù)。

為什么可以不實(shí)現(xiàn) equals(Object obj) 函數(shù)呢?
因?yàn)槿魏晤?lèi),默認(rèn)都是已經(jīng)實(shí)現(xiàn)了equals(Object obj)的。 Java中的一切類(lèi)都是繼承于java.lang.Object,在Object.java中實(shí)現(xiàn)了equals(Object obj)函數(shù);所以,其它所有的類(lèi)也相當(dāng)于都實(shí)現(xiàn)了該函數(shù)。

  • int compare(T o1, T o2) 是“比較o1和o2的大小”。返回“負(fù)數(shù)”,意味著“o1比o2小”;返回“零”,意味著“o1等于o2”;返回“正數(shù)”,意味著“o1大于o2”。
Comparable和Comparator的比較:

共同點(diǎn):Comparable & Comparator 都是用來(lái)實(shí)現(xiàn)集合中元素的比較、排序的。當(dāng)我們定義的某個(gè)類(lèi)需要進(jìn)行排序時(shí),就要考慮實(shí)現(xiàn)Comparable或Comparator接口。

我們定義一個(gè)Person,要求其根據(jù)id進(jìn)行排序:

實(shí)現(xiàn)Comparable接口

public class Person implements Comparable<Person>{
    private int id;
    private String name;
    private int age;

    public Person(int id,String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person o) {
        return this.id - o.id;
    }

    @Override
    public String toString() {
        return "id: " + id + " name: " + name + "  age: " + age;
    }

    public static void main(String[] args){
        List<Person> list = new ArrayList<>();
        list.add(new Person(3,"John",18));
        list.add(new Person(1,"Marry",21));
        list.add(new Person(2,"Tom",20));
        System.out.println("Before sort:");
        printList(list);
        Collections.sort(list);
        System.out.println("After sort:");
        printList(list);
    }

    public static void printList(List<Person> list){
        for (Person p : list){
            System.out.print(p + " / ");
        }
        System.out.println();
    }
}

輸出結(jié)果:
Before sort:
id: 3 name: John  age: 18 / id: 1 name: Marry  age: 21 / id: 2 name: Tom  age: 20 / 
After sort:
id: 1 name: Marry  age: 21 / id: 2 name: Tom  age: 20 / id: 3 name: John  age: 18 /

我們可以看到person類(lèi)中實(shí)現(xiàn)了Comparable接口,并重寫(xiě)了CompareTo方法。

實(shí)現(xiàn)Comparator接口

public class Person{
    private int id;
    private String name;
    private int age;

    public Person(int id,String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "id: " + id + " name: " + name + "  age: " + age;
    }

    public static void main(String[] args){
        List<Person> list = new ArrayList<>();
        list.add(new Person(3,"John",18));
        list.add(new Person(1,"Marry",21));
        list.add(new Person(2,"Tom",20));
        System.out.println("Before sort:");
        printList(list);
        //調(diào)用sort函數(shù),并傳入自定義Comparator
        Collections.sort(list,new MyComparator());
        System.out.println("After sort:");
        printList(list);
    }
    
    //自定義Comparator接口,并重寫(xiě)compare方法
    private static class MyComparator implements Comparator<Person>{

        @Override
        public int compare(Person o1, Person o2) {
            return o1.id - o2.id;
        }
    }

    private static void printList(List<Person> list){
        for (Person p : list){
            System.out.print(p + " / ");
        }
        System.out.println();
    }
}

通過(guò)上面的兩種實(shí)現(xiàn)方式:

區(qū)別:

  • Comparable接口是在集合內(nèi)部定義的方法實(shí)現(xiàn)的排序。
  • Comparator接口是在集合外部實(shí)現(xiàn)的排序。
  • 簡(jiǎn)單來(lái)說(shuō),comparable接口是通過(guò)類(lèi)自己完成比較,而comparator接口是通過(guò)外部程序?qū)崿F(xiàn)比較。

若同時(shí)實(shí)現(xiàn)Comparable接口和Comparator接口,排序會(huì)聽(tīng)哪個(gè)的呢?

我們?cè)O(shè)置Comparable接口實(shí)現(xiàn)升序,而Comparator接口實(shí)現(xiàn)降序。

public class Person implements Comparable<Person>{
    private int id;
    private String name;
    private int age;

    public Person(int id,String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person o) {
        return id - o.id;
    }

    @Override
    public String toString() {
        return "id: " + id + " name: " + name + "  age: " + age;
    }

    public static void main(String[] args){
        List<Person> list = new ArrayList<>();
        list.add(new Person(3,"John",18));
        list.add(new Person(1,"Marry",21));
        list.add(new Person(2,"Tom",20));
        System.out.println("Before sort:");
        printList(list);
        //調(diào)用sort函數(shù),并傳入自定義Comparator
        Collections.sort(list,new MyComparator());
        System.out.println("After sort:");
        printList(list);
    }



    //自定義Comparator接口,并重寫(xiě)compare方法
    private static class MyComparator implements Comparator<Person>{

        @Override
        public int compare(Person o1, Person o2) {
            return o2.id - o1.id;
        }
    }

    private static void printList(List<Person> list){
        for (Person p : list){
            System.out.print(p + " / ");
        }
        System.out.println();
    }
}

輸出結(jié)果:
Before sort:
id: 3 name: John  age: 18 / id: 1 name: Marry  age: 21 / id: 2 name: Tom  age: 20 / 
After sort:
id: 3 name: John  age: 18 / id: 2 name: Tom  age: 20 / id: 1 name: Marry  age: 21 / 

我們可以看到,最后的結(jié)果是以降序方式輸出的。也就意味著comparator接口優(yōu)先于comparable接口。

實(shí)際上,對(duì)于sort排序方法,若傳入自定義的comparator接口,則會(huì)以傳入的comparator方法來(lái)實(shí)現(xiàn)排序,否則,會(huì)使用類(lèi)本身的comparable接口方法。

何時(shí)使用comparable,何時(shí)使用comparator?
  • 若我們?cè)趯?duì)要排序的類(lèi)的排序規(guī)則比較固定,也就是不常修改時(shí),我們考慮實(shí)現(xiàn)comparable接口。
  • 若我們對(duì)要排序的類(lèi)的排序規(guī)則是經(jīng)常變化的,那么我們考慮實(shí)現(xiàn)comparator接口。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,787評(píng)論 11 349
  • Java集合框架 Java平臺(tái)提供了一個(gè)全新的集合框架。“集合框架”主要由一組用來(lái)操作對(duì)象的接口組成。不同接口描述...
    小石38閱讀 448評(píng)論 0 0
  • 項(xiàng)目中經(jīng)常會(huì)遇到列表搜索查詢(xún),大部分的查詢(xún)是可以通過(guò)sql語(yǔ)句來(lái)實(shí)現(xiàn)的,有些特殊的搜索排序sql則實(shí)現(xiàn)不了,例如中...
    信徒_allen閱讀 2,708評(píng)論 0 1
  • Java中提供了兩種對(duì)集合或數(shù)組中元素進(jìn)行排序的方法,一種是實(shí)現(xiàn)Comparable接口,另一種是實(shí)現(xiàn)Compar...
    EakonZhao閱讀 8,687評(píng)論 0 9
  • 前面兩種方式(plist文件讀寫(xiě)、NSUserDefaults偏好設(shè)置)只能保存 plist 支持的基本數(shù)據(jù)類(lèi)型,...
    伯牙呀閱讀 1,899評(píng)論 2 3

友情鏈接更多精彩內(nèi)容