Java 中 Comparable 和 Comparator 比較

Comparable 簡(jiǎn)介

Comparable 是排序接口。

若一個(gè)類(lèi)實(shí)現(xiàn)了Comparable接口,就意味著“該類(lèi)支持排序”。即然實(shí)現(xiàn)Comparable接口的類(lèi)支持排序,假設(shè)現(xiàn)在存在“實(shí)現(xiàn)Comparable接口的類(lèi)的對(duì)象的List列表(或數(shù)組)”,則該List列表(或數(shù)組)可以通過(guò) Collections.sort(或 Arrays.sort)進(jìn)行排序。

此外,“實(shí)現(xiàn)Comparable接口的類(lèi)的對(duì)象”可以用作“有序映射(如TreeMap)”中的鍵或“有序集合(TreeSet)”中的元素,而不需要指定比較器。


Comparable 定義

Comparable 接口僅僅只包括一個(gè)函數(shù),它的定義如下:

package java.lang;importjava.util.*;

publicinterfaceComparable {

? ? public int compareTo(T o);

}

說(shuō)明:

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

Comparator 簡(jiǎn)介

Comparator 是比較器接口。

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

也就是說(shuō),我們可以通過(guò)“實(shí)現(xiàn)Comparator類(lèi)來(lái)新建一個(gè)比較器”,然后通過(guò)該比較器對(duì)類(lèi)進(jìn)行排序。


Comparator 定義

Comparator 接口僅僅只包括兩個(gè)個(gè)函數(shù),它的定義如下:

package java.util;

public interface Comparator<T> {

? ? int compare(T o1, T o2);

? ? boolean equals(Object obj);

}

實(shí)例


import java.util.*;

import java.lang.Comparable;

/**

* @desc "Comparator"和“Comparable”的比較程序。

*? (01) "Comparable"

*? 它是一個(gè)排序接口,只包含一個(gè)函數(shù)compareTo()。

*? 一個(gè)類(lèi)實(shí)現(xiàn)了Comparable接口,就意味著“該類(lèi)本身支持排序”,它可以直接通過(guò)Arrays.sort() 或 Collections.sort()進(jìn)行排序。

*? (02) "Comparator"

*? 它是一個(gè)比較器接口,包括兩個(gè)函數(shù):compare() 和 equals()。

*? 一個(gè)類(lèi)實(shí)現(xiàn)了Comparator接口,那么它就是一個(gè)“比較器”。其它的類(lèi),可以根據(jù)該比較器去排序。

*

*? 綜上所述:Comparable是內(nèi)部比較器,而Comparator是外部比較器。

*? 一個(gè)類(lèi)本身實(shí)現(xiàn)了Comparable比較器,就意味著它本身支持排序;若它本身沒(méi)實(shí)現(xiàn)Comparable,也可以通過(guò)外部比較器Comparator進(jìn)行排序。

*/

public class CompareComparatorAndComparableTest{

? ? public static void main(String[] args) {

? ? ? ? // 新建ArrayList(動(dòng)態(tài)數(shù)組)

? ? ? ? ArrayList<Person> list = new ArrayList<Person>();

? ? ? ? // 添加對(duì)象到ArrayList中

? ? ? ? list.add(new Person("ccc", 20));

? ? ? ? list.add(new Person("AAA", 30));

? ? ? ? list.add(new Person("bbb", 10));

? ? ? ? list.add(new Person("ddd", 40));

? ? ? ? // 打印list的原始序列

? ? ? ? System.out.printf("Original? sort, list:%s\n", list);

? ? ? ? // 對(duì)list進(jìn)行排序

? ? ? ? // 這里會(huì)根據(jù)“Person實(shí)現(xiàn)的Comparable<String>接口”進(jìn)行排序,即會(huì)根據(jù)“name”進(jìn)行排序

? ? ? ? Collections.sort(list);

? ? ? ? System.out.printf("Name? ? ? sort, list:%s\n", list);

? ? ? ? // 通過(guò)“比較器(AscAgeComparator)”,對(duì)list進(jìn)行排序

? ? ? ? // AscAgeComparator的排序方式是:根據(jù)“age”的升序排序

? ? ? ? Collections.sort(list, new AscAgeComparator());

? ? ? ? System.out.printf("Asc(age)? sort, list:%s\n", list);

? ? ? ? // 通過(guò)“比較器(DescAgeComparator)”,對(duì)list進(jìn)行排序

? ? ? ? // DescAgeComparator的排序方式是:根據(jù)“age”的降序排序

? ? ? ? Collections.sort(list, new DescAgeComparator());

? ? ? ? System.out.printf("Desc(age) sort, list:%s\n", list);

? ? ? ? // 判斷兩個(gè)person是否相等

? ? ? ? testEquals();

? ? }

? ? /**

? ? * @desc 測(cè)試兩個(gè)Person比較是否相等。

? ? *? 由于Person實(shí)現(xiàn)了equals()函數(shù):若兩person的age、name都相等,則認(rèn)為這兩個(gè)person相等。

? ? *? 所以,這里的p1和p2相等。

? ? *

? ? *? TODO:若去掉Person中的equals()函數(shù),則p1不等于p2

? ? */

? ? private static void testEquals() {

? ? ? ? Person p1 = new Person("eee", 100);

? ? ? ? Person p2 = new Person("eee", 100);

? ? ? ? if (p1.equals(p2)) {

? ? ? ? ? ? System.out.printf("%s EQUAL %s\n", p1, p2);

? ? ? ? } else {

? ? ? ? ? ? System.out.printf("%s NOT EQUAL %s\n", p1, p2);

? ? ? ? }

? ? }

? ? /**

? ? * @desc Person類(lèi)。

? ? *? ? ? Person實(shí)現(xiàn)了Comparable接口,這意味著Person本身支持排序

? ? */

? ? private static class Person implements Comparable<Person>{

? ? ? ? int age;

? ? ? ? String name;

? ? ? ? public Person(String name, int age) {

? ? ? ? ? ? this.name = name;

? ? ? ? ? ? this.age = age;

? ? ? ? }

? ? ? ? public String getName() {

? ? ? ? ? ? return name;

? ? ? ? }

? ? ? ? public int getAge() {

? ? ? ? ? ? return age;

? ? ? ? }

? ? ? ? public String toString() {

? ? ? ? ? ? return name + " - " +age;

? ? ? ? }

? ? ? ? /**

? ? ? ? * 比較兩個(gè)Person是否相等:若它們的name和age都相等,則認(rèn)為它們相等

? ? ? ? */

? ? ? ? boolean equals(Person person) {

? ? ? ? ? ? if (this.age == person.age && this.name == person.name)

? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? /**

? ? ? ? * @desc 實(shí)現(xiàn) “Comparable<String>” 的接口,即重寫(xiě)compareTo<T t>函數(shù)。

? ? ? ? *? 這里是通過(guò)“person的名字”進(jìn)行比較的

? ? ? ? */

? ? ? ? @Override

? ? ? ? public int compareTo(Person person) {

? ? ? ? ? ? return name.compareTo(person.name);

? ? ? ? ? ? //return this.name - person.name;

? ? ? ? }

? ? }

? ? /**

? ? * @desc AscAgeComparator比較器

? ? *? ? ? 它是“Person的age的升序比較器”

? ? */

? ? private static class AscAgeComparator implements Comparator<Person> {


? ? ? ? @Override

? ? ? ? public int compare(Person p1, Person p2) {

? ? ? ? ? ? return p1.getAge() - p2.getAge();

? ? ? ? }

? ? }

? ? /**

? ? * @desc DescAgeComparator比較器

? ? *? ? ? 它是“Person的age的升序比較器”

? ? */

? ? private static class DescAgeComparator implements Comparator<Person> {


? ? ? ? @Override

? ? ? ? public int compare(Person p1, Person p2) {

? ? ? ? ? ? return p2.getAge() - p1.getAge();

? ? ? ? }

? ? }

}

運(yùn)行程序,輸出如下:

Original? sort, list:[ccc - 20, AAA - 30, bbb - 10, ddd - 40]

Name? ? ? sort, list:[AAA - 30, bbb - 10, ccc - 20, ddd - 40]

Asc(age)? sort, list:[bbb - 10, ccc - 20, AAA - 30, ddd - 40]

Desc(age) sort, list:[ddd - 40, AAA - 30, ccc - 20, bbb - 10]

eee - 100 EQUAL eee - 100

?著作權(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)容

  • 項(xiàng)目中經(jīng)常會(huì)遇到列表搜索查詢,大部分的查詢是可以通過(guò)sql語(yǔ)句來(lái)實(shí)現(xiàn)的,有些特殊的搜索排序sql則實(shí)現(xiàn)不了,例如中...
    信徒_allen閱讀 2,727評(píng)論 0 1
  • 排序 在java 中我們對(duì)ArraryList 中的數(shù)據(jù)進(jìn)行排序;通??梢允褂肅ollections.sort()...
    say_hello閱讀 1,038評(píng)論 0 50
  • Streams 的背景,以及 Java 8 中的使用詳解 為什么需要 Stream Stream 作為 Java ...
    Java黎先生閱讀 869評(píng)論 0 8
  • 實(shí)現(xiàn) Comparable實(shí)現(xiàn)比較器Comparable實(shí)現(xiàn)比較器,是定義在Person類(lèi)的內(nèi)部的,因此實(shí)體類(lèi)Pe...
    上杉丶零閱讀 945評(píng)論 0 1
  • 念念叨叨,語(yǔ)語(yǔ)切切真真,逆耳忠言; 碎碎言言,字字情情義義,義薄云天; 點(diǎn)點(diǎn)滴滴,片片深深入入,是非不辯 支支吾吾...
    瘋子笑言書(shū)閱讀 339評(píng)論 0 0

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