Java 比較器 Comparable 與 Comparator

Comparable

Comparable 是排序接口,若一個類實現(xiàn)了 Comparable 接口,就意味著 “該類支持排序”。假設(shè)現(xiàn)在存在 “實現(xiàn) Comparable 接口的類的對象的集合(或數(shù)組)”,則該集合(或數(shù)組)可以通過 Collections.sort(或 Arrays.sort)進行排序。

Comparable 定義

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

實現(xiàn) Comparable 接口的類必須實現(xiàn) compareTo 方法,對象就可以比較大小。假設(shè)我們通過 x.compareTo(y) 來 “比較 x 和 y 的大小”。若返回 “負數(shù)”,意味著 “x 比 y 小”;返回 “零”,意味著 “x 等于 y”;返回 “正數(shù)”,意味著 “x 大于 y”。

public class Student implements Comparable {
     String name;
     public int compareTo(Student another) {
         return name.compareTo(another.name); 
     }
}

// 比較兩個對象
student1.compareTo(student2);

// 排序數(shù)組或集合
Arrays.sort(students);
Collections.sort(collection);

Java 的一些常用類已經(jīng)實現(xiàn)了 Comparable 接口,并提供了比較大小的標(biāo)準(zhǔn)。比如包裝類按照它們對應(yīng)的數(shù)值大小進行比較。String,Date,Time 等也都實現(xiàn)了 Comparable 接口。一個類如果實現(xiàn) Comparable 接口,那么它就具有了可比較性。

分析比較器的排序原理

實際上比較器的操作,就是經(jīng)常聽到的二叉樹的排序算法。

排序的基本原理:使用第一個元素作為根節(jié)點,之后如果后面的內(nèi)容比根節(jié)點小,則放在左子樹,如果內(nèi)容比根節(jié)點的內(nèi)容要大,則放在右子樹。

Comparator

我們?nèi)粜枰刂颇硞€類的次序,而該類本身不支持排序(即沒有實現(xiàn) Comparable 接口);那么,我們可以建立一個 “該類的比較器” 來進行排序。這個 “比較器” 只需要實現(xiàn) Comparator 接口即可。

Comparator 定義

package java.util;
public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

若一個類要實現(xiàn) Comparator 接口,它一定要實現(xiàn) compareTo(T o1, T o2) 函數(shù),但可以不實現(xiàn) equals(Object obj) 函數(shù)。Object 類是所有類的父類,也就是說實現(xiàn)接口的子類已經(jīng)重寫了 equals 方法。

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

在不希望修改一個原有的類,或提供的比較器不適用時,就需要使用外部比較器,比如 String 類實現(xiàn)
Comparable<String>,而且 String.compareTo() 是按字典序比較字符串的,這時如果需要按長度對字符串進行排序,就不能讓 String 類用兩種不同的方法實現(xiàn) compareTo 方法了,更何況,String 類也不應(yīng)該由我們來修改,這時就需要使用外部比較器:

class LengthComparator implements Comparator<String> {
    public int compare(String f, String s) {
        return f.length() - s.length();
    }
}

// 比較兩個對象
LengthComparator comparator = new LengthComparator();
comparator.compare(person1,person2);

// 排序數(shù)組或集合
Arrays.sort(arr, new LengthComparator());
Collections.sort(collection, new LengthComparator());

Comparator 體現(xiàn)了策略模式,就是不改變對象自身,而用一個策略對象來改變它的行為。

Comparator 和 Comparable 區(qū)別

內(nèi)部比較器 Comparable 是排序接口,只包含一個函數(shù) compareTo();若一個類實現(xiàn)了 Comparable 接口,就意味著 “該類支持排序”,它可以直接通過 Arrays.sort() 或 Collections.sort() 進行排序。

外部比較器 Comparator 是比較器接口,單獨實現(xiàn)第一個比較器,不需要對原來的類進行結(jié)構(gòu)上的變化,屬于無侵入式的;一個類實現(xiàn)了 Comparator 接口,那么它就是一個 “比較器”。其它的類,可以根據(jù)該比較器去排序。

一個類本身實現(xiàn)了 Comparable 接口,就意味著它本身支持排序;若它本身沒實現(xiàn) Comparable,也可以通過外部比較器 Comparator 進行排序。

  • 如果比較的方法只要用在一個類中,用該類實現(xiàn) Comparable 接口就可以。
  • 如果比較的方法在很多類中需要用到,就自己寫個類實現(xiàn) Comparator 接口,這樣當(dāng)要比較的時候把實現(xiàn)了 Comparator 接口的類傳過去就可以,省得重復(fù)造輪子。這也是為什么 Comparator 會在 java.util 包下的原因。

使用 Comparator 的優(yōu)點:

  1. 與實體類分離
  2. 方便應(yīng)對多變的排序規(guī)則,可以同時使用多種排序標(biāo)準(zhǔn)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,340評論 11 349
  • 項目中經(jīng)常會遇到列表搜索查詢,大部分的查詢是可以通過sql語句來實現(xiàn)的,有些特殊的搜索排序sql則實現(xiàn)不了,例如中...
    信徒_allen閱讀 2,601評論 0 1
  • Java集合框架 Java平臺提供了一個全新的集合框架?!凹峡蚣堋敝饕梢唤M用來操作對象的接口組成。不同接口描述...
    小石38閱讀 366評論 0 0
  • 某天老板說:要不這個改成這個吧,雨聲,你怎么看?運營說:雨聲,你輸了,看看人家的設(shè)計!商務(wù)說:商家說,“官人,人家...
    雨聲閱讀 637評論 0 51
  • 感賞自己早上起來,看到兒子正在擺弄手機,但沒玩游戲,盡管心里有厭煩,神情還是很自然。我平生最討厭早上一起床,就打開...
    玫瑰鏗鏘閱讀 177評論 0 1