java對(duì)象對(duì)比之comparable和comparator的區(qū)別
一、元素的比較
1.1 基本類(lèi)型的比較
java中的基本類(lèi)型的對(duì)象是可以進(jìn)行比較的
如
public static void main(String[] args){
int a = 10;
int b = 20;
System.out.println(a>b);
System.out.println(a==b);
System.out.println(a<b);
char c1 = 'A';
char c2 = 'B';
System.out.println(c1>c2);
System.out.println(c1==c2);
System.out.println(c1<c2);
boolean b1 = true;
boolean b2 =false;
System.out.println(b1==b2);
System.out.println(b1!=b2);
}

1.2 對(duì)象的比較
public class Main{
public static void main(String[] args){
Card c1 = new Card(1,"♠");
Card c2 = new Card(2,"♠");
Card c3 = c1;
System.out.println(c1==c2);
System.out.println(c1==c3);
// System.out.println(c1>c2); 編譯報(bào)錯(cuò)
// System.out.println(c1<c2); 編譯報(bào)錯(cuò)
}
}
class Card{
public int rank;
public String suit;
public Card(int rank,String suit){
this.rank = rank;
this.suit = suit;
}
}

可以看出在進(jìn)行相等比較時(shí),是可以進(jìn)行比較的,但進(jìn)行大于或小于比較就不行了
這是因?yàn)閷?duì)于用戶實(shí)現(xiàn)自定義類(lèi)型,都默認(rèn)繼承自O(shè)bject類(lèi),而Object類(lèi)中提供了equal方法,而==默認(rèn)情況下調(diào)用的就是equal方法,但是該方法的比較規(guī)則是:沒(méi)有比較引用變量引用對(duì)象的內(nèi)容,而是直接比較引用變量的地址,但有些情況下該種比較就不符合題意。
二、對(duì)象的比較
有些情況下,需要比較的是對(duì)象中的內(nèi)容,比如:向優(yōu)先級(jí)隊(duì)列中插入某個(gè)對(duì)象時(shí),需要對(duì)按照對(duì)象中內(nèi)容來(lái)調(diào)整堆,那該如何處理呢?
2.1 覆寫(xiě)基類(lèi)的equal

一般覆寫(xiě) equals 的套路就是上面演示的
1.如果指向同一個(gè)對(duì)象,返回 true
2.如果傳入的為 null,返回 false
3.如果傳入的對(duì)象類(lèi)型不是 Card,返回 false
4.按照類(lèi)的實(shí)現(xiàn)目標(biāo)完成比較,例如這里只要花色和數(shù)值一樣,就認(rèn)為是相同的牌
5.注意下調(diào)用其他引用類(lèi)型的比較也需要 equals,例如這里的 suit 的比較
覆寫(xiě)基類(lèi)equal的方式雖然可以比較,但缺陷是:equal只能按照相等進(jìn)行比較,不能按照大于、小于的方式進(jìn)行比較。
2.2 基于Comparable接口的比較
Comparble是JDK提供的泛型的比較接口類(lèi),源碼實(shí)現(xiàn)具體如下:
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
* <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
* -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>x.compareTo(y)</tt> must throw an exception iff
* <tt>y.compareTo(x)</tt> throws an exception.)
*
* <p>The implementor must also ensure that the relation is transitive:
* <tt>(x.compareTo(y)>0 && y.compareTo(z)>0)</tt> implies
* <tt>x.compareTo(z)>0</tt>.
*
* <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
* implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
* all <tt>z</tt>.
*
* <p>It is strongly recommended, but <i>not</i> strictly required that
* <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>. Generally speaking, any
* class that implements the <tt>Comparable</tt> interface and violates
* this condition should clearly indicate this fact. The recommended
* language is "Note: this class has a natural ordering that is
* inconsistent with equals."
*
* <p>In the foregoing description, the notation
* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
* <tt>0</tt>, or <tt>1</tt> according to whether the value of
* <i>expression</i> is negative, zero or positive.
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
可以看到在Comparable接口中只實(shí)現(xiàn)了一個(gè)方法 compareTo,因此我們?cè)趯?shí)現(xiàn)自定義比較時(shí),在類(lèi)的定義中實(shí)現(xiàn)Comparable接口即可,然后在類(lèi)中重寫(xiě)compareTo方法
public class Main{
public static void main(String[] args){
Card c1 = new Card(1,"♠");
Card c2 = new Card(2,"♠");
Card c3 = c1;
System.out.println(c1.compareTo(c2));
System.out.println(c1.compareTo(c3));
System.out.println(c2.compareTo(c3));
}
}
class Card implements Comparable<Card>{
public int rank;
public String suit;
public Card(int rank,String suit){
this.rank = rank;
this.suit = suit;
}
@Override
public int compareTo(Card o) {
if(o==null){
return 1;
}
return rank-o.rank;
}
}

當(dāng)前值比要比較值小則輸出-1;當(dāng)前值與要比較值相等則輸出0;
當(dāng)前值比要比較值大輸出1;
2.3 基于比較器Comparator的比較
首先了解一下Comparator接口
public interface Comparator<T> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
*
* In the foregoing description, the notation
* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
* <tt>0</tt>, or <tt>1</tt> according to whether the value of
* <i>expression</i> is negative, zero or positive.<p>
*
* The implementor must ensure that <tt>sgn(compare(x, y)) ==
* -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>compare(x, y)</tt> must throw an exception if and only
* if <tt>compare(y, x)</tt> throws an exception.)<p>
*
* The implementor must also ensure that the relation is transitive:
* <tt>((compare(x, y)>0) && (compare(y, z)>0))</tt> implies
* <tt>compare(x, z)>0</tt>.<p>
*
* Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
* implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
* <tt>z</tt>.<p>
*
* It is generally the case, but <i>not</i> strictly required that
* <tt>(compare(x, y)==0) == (x.equals(y))</tt>. Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
當(dāng)然還有許多comparator實(shí)現(xiàn)的自定義比較方法,但這里我只貼出需要自己實(shí)現(xiàn)的方法compare;
接下來(lái)看看comparator的用法
當(dāng)使用comparator時(shí),如果要使用自定義的比較方式需要實(shí)現(xiàn)comparator接口,并且覆寫(xiě)compare方法;因此需要自己構(gòu)造一個(gè)比較器類(lèi)實(shí)現(xiàn)comparator接口,然后利用我們自定義的比較器進(jìn)行比較即可;
下面是一個(gè)應(yīng)用實(shí)例
// write your code here
import java.util.*;
import java.lang.*;
public class Main{
public static void main(String[] args){
Card c1 = new Card(1,"♠");
Card c2 = new Card(2,"♠");
Card c3 = c1;
CardComparator cardComparator = new CardComparator();
System.out.println(cardComparator.compare(c1,c2));
System.out.println(cardComparator.compare(c1,c3));
System.out.println(cardComparator.compare(c2,c3));
}
}
class Card {
public int rank;
public String suit;
public Card(int rank,String suit){
this.rank = rank;
this.suit = suit;
}
}
class CardComparator implements Comparator<Card>{
@Override
public int compare(Card o1, Card o2) {
if (o1==o2){
return 0;
}
if (o1==null)return -1;
if (o2==null)return 1;
return o1.rank-o2.rank;
}
}

Comparator屬于java.util包中泛型接口類(lèi),使用時(shí)必須導(dǎo)入相關(guān)的包;
我們將Comparator中的compare方法重寫(xiě),就可以對(duì)需要進(jìn)行對(duì)比的對(duì)象進(jìn)行對(duì)比并返回結(jié)果。
2.4 幾種不同的compare對(duì)比
| 方法 | 說(shuō)明 |
|---|---|
| object.equals | 直接覆寫(xiě)即可,不過(guò)只能比較相等與否 |
| Comparable.compareTO | 需要手動(dòng)實(shí)現(xiàn)接口,當(dāng)前類(lèi)之后的所有對(duì)比方式都被定義,屬于內(nèi)部順序 |
| Comparator.compare | 需要實(shí)現(xiàn)一個(gè)比較器對(duì)象,對(duì)待比較類(lèi)的侵入性弱,但對(duì)代碼的侵入性強(qiáng) |
到此這篇關(guān)于java對(duì)象對(duì)比之comparable和comparator的區(qū)別的文章就介紹到這了,更多相關(guān)comparable和comparator的區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java并發(fā)編程工具類(lèi)JUC之ArrayBlockingQueue
類(lèi)ArrayBlockingQueue是BlockingQueue接口的實(shí)現(xiàn)類(lèi),它是有界的阻塞隊(duì)列,內(nèi)部使用數(shù)組存儲(chǔ)隊(duì)列元素,通過(guò)代碼給大家說(shuō)明如何初始化一個(gè)ArrayBlockingQueue,并向其中添加一個(gè)對(duì)象,對(duì)java并發(fā)編程工具類(lèi)ArrayBlockingQueue相關(guān)知識(shí)感興趣的朋友一起看看吧2021-05-05
解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問(wèn)題
這篇文章主要介紹了解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
解決@Scope(“prototype“)不生效的問(wèn)題
這篇文章主要介紹了解決@Scope(“prototype“)不生效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
mybatis-plus中wrapper的用法實(shí)例詳解
本文給大家介紹了mybatis-plus中wrapper的用法,包括條件構(gòu)造器關(guān)系、項(xiàng)目實(shí)例及具體使用操作,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
Java使用easyExcel實(shí)現(xiàn)導(dǎo)入功能
這篇文章介紹了Java使用easyExcel實(shí)現(xiàn)導(dǎo)入功能的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
SpringBoot @ExceptionHandler與@ControllerAdvice異常處理詳解
在Spring Boot應(yīng)用的開(kāi)發(fā)中,不管是對(duì)底層數(shù)據(jù)庫(kù)操作,對(duì)業(yè)務(wù)層操作,還是對(duì)控制層操作,都會(huì)不可避免的遇到各種可預(yù)知的,不可預(yù)知的異常需要處理,如果每個(gè)處理過(guò)程都單獨(dú)處理異常,那么系統(tǒng)的代碼耦合度會(huì)很高,工作量大且不好統(tǒng)一,以后維護(hù)的工作量也很大2022-10-10
Linux中Elasticsearch的安裝詳細(xì)步驟
這篇文章主要介紹了Linux中Elasticsearch的安裝詳細(xì)步驟,Elasticsearch(ES)是一種分布式、可擴(kuò)展的搜索和分析引擎,基于Lucene構(gòu)建,它支持實(shí)時(shí)數(shù)據(jù)處理、全文搜索、實(shí)時(shí)分析等多種功能,需要的朋友可以參考下2024-12-12

