java對(duì)象對(duì)比之comparable和comparator的區(qū)別
一、元素的比較
1.1 基本類型的比較
java中的基本類型的對(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)自定義類型,都默認(rèn)繼承自O(shè)bject類,而Object類中提供了equal方法,而==默認(rèn)情況下調(diào)用的就是equal方法,但是該方法的比較規(guī)則是:沒有比較引用變量引用對(duì)象的內(nèi)容,而是直接比較引用變量的地址,但有些情況下該種比較就不符合題意。
二、對(duì)象的比較
有些情況下,需要比較的是對(duì)象中的內(nèi)容,比如:向優(yōu)先級(jí)隊(duì)列中插入某個(gè)對(duì)象時(shí),需要對(duì)按照對(duì)象中內(nèi)容來調(diào)整堆,那該如何處理呢?
2.1 覆寫基類的equal
一般覆寫 equals 的套路就是上面演示的
1.如果指向同一個(gè)對(duì)象,返回 true
2.如果傳入的為 null,返回 false
3.如果傳入的對(duì)象類型不是 Card,返回 false
4.按照類的實(shí)現(xiàn)目標(biāo)完成比較,例如這里只要花色和數(shù)值一樣,就認(rèn)為是相同的牌
5.注意下調(diào)用其他引用類型的比較也需要 equals,例如這里的 suit 的比較
覆寫基類equal的方式雖然可以比較,但缺陷是:equal只能按照相等進(jìn)行比較,不能按照大于、小于的方式進(jìn)行比較。
2.2 基于Comparable接口的比較
Comparble是JDK提供的泛型的比較接口類,源碼實(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í),在類的定義中實(shí)現(xiàn)Comparable接口即可,然后在類中重寫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;
接下來看看comparator的用法
當(dāng)使用comparator時(shí),如果要使用自定義的比較方式需要實(shí)現(xiàn)comparator接口,并且覆寫compare方法;因此需要自己構(gòu)造一個(gè)比較器類實(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包中泛型接口類,使用時(shí)必須導(dǎo)入相關(guān)的包;
我們將Comparator中的compare方法重寫,就可以對(duì)需要進(jìn)行對(duì)比的對(duì)象進(jìn)行對(duì)比并返回結(jié)果。
2.4 幾種不同的compare對(duì)比
方法 | 說明 |
---|---|
object.equals | 直接覆寫即可,不過只能比較相等與否 |
Comparable.compareTO | 需要手動(dòng)實(shí)現(xiàn)接口,當(dāng)前類之后的所有對(duì)比方式都被定義,屬于內(nèi)部順序 |
Comparator.compare | 需要實(shí)現(xiàn)一個(gè)比較器對(duì)象,對(duì)待比較類的侵入性弱,但對(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)文章
Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的全過程
前后端分離是目前互聯(lián)網(wǎng)開發(fā)中比較廣泛使用的開發(fā)模式,主要是將前端和后端的項(xiàng)目業(yè)務(wù)進(jìn)行分離,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的相關(guān)資料,需要的朋友可以參考下2022-04-04java對(duì)象轉(zhuǎn)化成String類型的四種方法小結(jié)
在java項(xiàng)目的實(shí)際開發(fā)和應(yīng)用中,常常需要用到將對(duì)象轉(zhuǎn)為String這一基本功能。本文就詳細(xì)的介紹幾種方法,感興趣的可以了解一下2021-08-08MyBatis-Plus 使用枚舉自動(dòng)關(guān)聯(lián)注入
本文主要介紹了MyBatis-Plus 使用枚舉自動(dòng)關(guān)聯(lián)注入,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06Java利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了Java如何利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01spring security認(rèn)證異常后返回中文提示的問題
這篇文章主要介紹了spring security認(rèn)證異常后返回中文提示的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例
WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,允許服務(wù)器主動(dòng)向客戶端推送信息,同時(shí)也能從客戶端接收信息,本文主要介紹了SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例,感興趣的可以了解一下2024-08-08springboot配置mysql數(shù)據(jù)庫spring.datasource.url報(bào)錯(cuò)的解決
這篇文章主要介紹了springboot配置mysql數(shù)據(jù)庫spring.datasource.url報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01javacv開發(fā)詳解之調(diào)用本機(jī)攝像頭視頻
這篇文章主要介紹了javacv開發(fā)詳解之調(diào)用本機(jī)攝像頭視頻,對(duì)javacv感興趣的同學(xué),可以參考下2021-04-04