一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

2022-03-02 00:42@陌上初薰 Java教程

本文主要介紹了java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

關(guān)于對(duì)象值相等的比較

三種比較風(fēng)格

  • 比較身份:==,通過(guò)等號(hào)來(lái)比較身份
  • 比較值:通過(guò)使用equals方法,它是Object這個(gè)祖宗類(lèi)所提供的的一個(gè)方法,也可以自己寫(xiě)個(gè)類(lèi),重寫(xiě)equals,自定制比較值的規(guī)則。
  • 這里的equals需要通過(guò)用戶手動(dòng)重寫(xiě)才能夠按照值比較,換句話說(shuō)就是你要是想比較值的話,就要約定好你到底按照什么樣的規(guī)則來(lái)進(jìn)行比較,因?yàn)槿绻潜容^身份的話,編譯器比較清楚,可以比較引用的地址,但如果是比較值的話,你一個(gè)類(lèi)中有很多屬性,到底按哪些規(guī)則來(lái)比較,誰(shuí)重要誰(shuí)不重要,編譯器自己也不知道,這就需要用戶根據(jù)業(yè)務(wù)場(chǎng)景來(lái)指定按照哪些字段進(jìn)行比較。
  • 如果equals沒(méi)有手動(dòng)重寫(xiě),默認(rèn)執(zhí)行的就是Object版本中的equals,此時(shí)的比較規(guī)則也是在比較身份。
  • 比較類(lèi)型: 通過(guò)instanceof,在類(lèi)型轉(zhuǎn)型之前先比較一下,看看當(dāng)前引用的真實(shí)類(lèi)型到底是什么,以免出現(xiàn)類(lèi)型轉(zhuǎn)換異常。

驗(yàn)證== 和 equas在比較風(fēng)格上的區(qū)別

代碼實(shí)現(xiàn):按照身份來(lái)比較

package java2021_1018;
//寫(xiě)一個(gè)輔助的類(lèi)Card(撲克牌-之前寫(xiě)過(guò))
class Card{
  //按照點(diǎn)數(shù)來(lái)比較
  public String rank;//點(diǎn)數(shù)
  public String suit;//花色
  //提供構(gòu)造方法
  public Card(String rank, String suit) {
      this.rank = rank;
      this.suit = suit;
  }
}
public class TestCompare {
  public static void main(String[] args) {
      //寫(xiě)一個(gè)類(lèi)方法,在類(lèi)方法中構(gòu)造出這兩張牌
      Card a=new Card("3","♠");//第一張牌:a的點(diǎn)數(shù)為1,花色為黑桃
      Card b=new Card("3","♠");//第二張牌:b的點(diǎn)數(shù)為1,花色為黑桃
      Card c=a;
      //此時(shí)已經(jīng)有了三張牌,但是這三張牌來(lái)的方式并不一樣,a是通過(guò)new一個(gè)Card對(duì)象,
      //b也是是通過(guò)new一個(gè)Card對(duì)象,而c是相當(dāng)于和直接a指向同一個(gè)card對(duì)象

      //《使用 == 等號(hào),進(jìn)行比較》
      System.out.println("==============使用 == 等號(hào),進(jìn)行比較的結(jié)果==============");
      System.out.println(a == c);//結(jié)果為true
      System.out.println(a == b);//結(jié)果為false
      //第二個(gè)結(jié)果為true是因?yàn)閍和b分別new了兩個(gè)對(duì)象,這兩個(gè)對(duì)象的身份是不相等的,所以執(zhí)行 == 比較就是false的情況
      //《使用equals進(jìn)行比較》
      System.out.println("==============使用equals進(jìn)行比較的結(jié)果==============");
      System.out.println(a.equals(c));//結(jié)果為true
      System.out.println(a.equals(b));//結(jié)果為false
      /*此時(shí)發(fā)現(xiàn)當(dāng)前使用的equals和 == 結(jié)果一樣,沒(méi)什么區(qū)別,這說(shuō)明當(dāng)前這個(gè)equals你沒(méi)有對(duì)他進(jìn)行重寫(xiě)的時(shí)候,它就仍然是按照身份的方式進(jìn)行比較的;
      * 所以,如果equals沒(méi)有手動(dòng)重寫(xiě),默認(rèn)執(zhí)行的就是Object版本中的equals,此時(shí)的比較規(guī)則也是在比較身份。*/
  }
}

打印結(jié)果:

java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

覆寫(xiě)基類(lèi)的equal

給equals加上一個(gè)重寫(xiě),使它變成比較值(內(nèi)容)的方法

代碼實(shí)現(xiàn):按照值來(lái)比較

package java2021_1018;

class Card{
  public String rank;//點(diǎn)數(shù)
  public String suit;//花色
  public Card(String rank, String suit) {
      this.rank = rank;
      this.suit = suit;
  }
  
  @Override
  public boolean equals(Object obj) {//參數(shù):obj,類(lèi)型:Object
      //按照值來(lái)比較this和obj
      //1.考慮自己和自己比較的情況
      if(this == obj){ //先看看比較的這兩個(gè)對(duì)象是不是同一個(gè)對(duì)象,如果是,就返回true
          return true;//因?yàn)閮蓚€(gè)對(duì)象(引用)如果身份相同的話,那么值也肯定是相同的
      }
      //2.考慮obj為null的情況,認(rèn)為結(jié)果為false, 避免出現(xiàn)空引用異常。 因?yàn)閠his是不可能為null的,如果它是null,就無(wú)法調(diào)用equals方法了
      //所以如果obj為null,this不為null,那就返回false,有了這樣的一個(gè)條件判斷,就可以保證在后面這個(gè)obj == null邏輯執(zhí)行的時(shí)候,就不會(huì)出現(xiàn)空引用異常了
      if(obj == null){
          return false;
      }
      //3、考慮類(lèi)型不匹配的情況,即考慮obj這個(gè)類(lèi)型是不是當(dāng)前的Card類(lèi)型,如果equals里傳了一個(gè)其他參數(shù)類(lèi)型進(jìn)來(lái),此時(shí)兩個(gè)類(lèi)型不同是無(wú)法比較相等的,所以需要判斷一下哦
      if (!(obj instanceof Card)){//如果obj這個(gè)參數(shù)不是Card這個(gè)類(lèi)型的話,就返回false
          return false;
          //同時(shí)類(lèi)型轉(zhuǎn)換也帶有類(lèi)型轉(zhuǎn)換失敗的風(fēng)險(xiǎn),所以在使用之前也要先確認(rèn)好類(lèi)型是否匹配
      }
      //4.真正的比較內(nèi)容
      Card other = (Card)obj;//此時(shí)的參數(shù)類(lèi)型是Object類(lèi)型,所以需要先對(duì)obj進(jìn)行一個(gè)類(lèi)型的強(qiáng)轉(zhuǎn),并賦值給一個(gè)變量other
      //再去比較判斷 點(diǎn)數(shù)或花色 或 點(diǎn)數(shù)和花色 是否相等
      return this.rank.equals(other.rank) && this.suit.equals(other.suit);
  }
  //這相當(dāng)于是一個(gè)標(biāo)準(zhǔn)的重寫(xiě)equals的一個(gè)模板,以后再寫(xiě)其他的一些自己的比較方法的時(shí)候也要按照這種思路一步步往下考慮
}
public class TestCompare1 {
  public static void main(String[] args) {
      Card a=new Card("3","♠");//第一張牌:a的點(diǎn)數(shù)為1,花色為黑桃
      Card b=new Card("3","♠");//第二張牌:b的點(diǎn)數(shù)為1,花色為黑桃
      Card c=a;      
      System.out.println("==============使用 == 等號(hào),進(jìn)行比較的結(jié)果==============");
      System.out.println(a == c);//結(jié)果為true
      System.out.println(a == b);//結(jié)果為true,因?yàn)閍和b分別new了兩個(gè)對(duì)象,這兩個(gè)對(duì)象的身份是不相等的,所以執(zhí)行 == 比較就是false的情況
      System.out.println("==============使用equals進(jìn)行比較的結(jié)果==============");        
      System.out.println(a.equals(c));//結(jié)果為true
      System.out.println(a.equals(b));//結(jié)果為true      
  }
}

打印結(jié)果:

java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

注意:一般覆寫(xiě) equals 的套路就是上面演示的

在實(shí)現(xiàn)equals中所需考慮的幾個(gè)步驟,及涉及到的細(xì)節(jié),在實(shí)現(xiàn)其他類(lèi)的equals時(shí)也基本上就是代碼中所考慮的這幾個(gè)操作(套路)。

  • 如果指向同一個(gè)對(duì)象,返回 true
  • 如果傳入的為 null,返回 false
  • 如果傳入的對(duì)象類(lèi)型不是 Card,返回 false
  • 按照類(lèi)的實(shí)現(xiàn)目標(biāo)完成比較,例如這里只要花色和數(shù)值一樣,就認(rèn)為是相同的牌
  • 注意下調(diào)用其他引用類(lèi)型的比較也需要 equals,例如這里的 suit 的比較
  • 覆寫(xiě)基類(lèi)equal的方式雖然可以比較,但缺陷是:equal只能按照相等進(jìn)行比較,不能按照大于、小于的方式進(jìn)行比較。

 

關(guān)于對(duì)象值大于、等于、小于的比較C基于自然順序(按照<小于號(hào)的形式)

基于Comparble接口類(lèi)的比較

Comparble這個(gè)接口相當(dāng)于就是重新定義小于這個(gè)操作

下面通過(guò)代碼來(lái)體會(huì)一下Comparble這個(gè)接口的作用,還是基于Card這個(gè)類(lèi)來(lái)進(jìn)行比較,如果想要使用Comparble這個(gè)接口的話,就需要讓Card實(shí)現(xiàn)一個(gè)Comparble,由于Comparble是一個(gè)帶泛型的接口,于是就需要給它寫(xiě)一個(gè)泛型參數(shù),但也不是非寫(xiě)不可。

java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

代碼實(shí)現(xiàn):基于Comparble接口類(lèi)的比較

package java2021_1018;

class Card  implements Comparable<Card>{//實(shí)現(xiàn)一個(gè) Comparable的接口,由于Comparble是一個(gè)帶泛型的接口,于是就需要給它寫(xiě)一個(gè)泛型參數(shù)
  //按照點(diǎn)數(shù)來(lái)比較
  public String rank;//點(diǎn)數(shù)
  public String suit;//花色
  //提供構(gòu)造方法
  public Card(String rank, String suit) {
      this.rank = rank;
      this.suit = suit;
  }
//重寫(xiě)compareTo方法
  @Override
  public int compareTo(Card o) {
      if(o == null){//如果o傳過(guò)來(lái)的參數(shù)是一個(gè)空引用,就認(rèn)為this比null要大
          //一般也認(rèn)為null的值比較小
          return 1;
      }
      //點(diǎn)數(shù)的取值:是2~10的一系列整數(shù),和J  Q  K  A;如果點(diǎn)數(shù)值在2~10的話,直接返回成整數(shù),如果點(diǎn)數(shù)值是J  Q  K  A的話,就手動(dòng)把這四個(gè)點(diǎn)數(shù)設(shè)置成11,12,13,14然后把值算出來(lái)之后再去分別比較大小
      int rank1 = this.getValue();//this的值
      int rank2 = o.getValue();//o的值
      return rank1-rank2;//返回二者的差值,返回的值參考compareTo的語(yǔ)法規(guī)則
  }
//寫(xiě)一個(gè)獲取值的方法,
  private int getValue() {
      //通過(guò)這個(gè)方法把String 類(lèi)型的rank(J  Q  K  A)變成數(shù)字點(diǎn)數(shù)11,12,13,14
      int value = 0;
      if("J".equals(rank)){
          value = 11;
      }else if("Q".equals(rank)){
          value = 12;
      }else if("K".equals(rank)){
          value = 13;
      }else if ("A".equals(rank)){
          value = 14;
      }else {
          value = Integer.parseInt(rank);//把字符串轉(zhuǎn)成數(shù)字
          //單獨(dú)處理J  Q  K  A,然后其他的2~10直接使用Integer.parseInt,把字符串轉(zhuǎn)換成整數(shù)。
      }
      return value;
  }

public class TestCompare1 {
  public static void main(String[] args) {
      //寫(xiě)一個(gè)類(lèi)方法,在類(lèi)方法中構(gòu)造出這兩張牌
      Card a=new Card("3","♠");//第一張牌:a的點(diǎn)數(shù)為1,花色為黑桃
      Card b=new Card("2","♦");//第二張牌:b的點(diǎn)數(shù)為1,花色為黑桃
      Card c=a;
      //調(diào)用compareTo比較方法
      System.out.println(a.compareTo(b));
      System.out.println(a.compareTo(c));
  }
}

compareTo方法的語(yǔ)法規(guī)則

  • 如果認(rèn)為this 比 o 小,就返回一個(gè)<0的整數(shù)
  • 如果認(rèn)為this 比 o 大,就返回一個(gè)>0的整數(shù)
  • 如果認(rèn)為this 比 o 相等,就返回0

不同的點(diǎn)數(shù)比較后所打印出來(lái)的結(jié)果如下圖:

java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別

 

關(guān)于對(duì)象值大于、等于、小于的比較-- 基于比較器比較

基于Comparator接口類(lèi)的比較

Comparator也是一個(gè)接口,想要使用它也要讓你的類(lèi)去實(shí)現(xiàn)這個(gè)接口,同時(shí)去重寫(xiě)一個(gè)compare方法,但是不同的是compare方法里面有兩個(gè)參數(shù),

Comparable和Comparator,他倆的區(qū)別在于Comparator定義出的比較器和原來(lái)的類(lèi)不是一個(gè)耦合在一起的關(guān)系

即使用Comparable的時(shí)候,你必須讓要比較的類(lèi)實(shí)現(xiàn)Comparable接口,換句話說(shuō),就是需要修改這個(gè)類(lèi)的代碼,比如剛才待比較類(lèi)是Card,如果要是用Comparable這種實(shí)現(xiàn)方式的時(shí)候,必須得修改Card的源碼。

而使用Comparator的時(shí)候,你是重新創(chuàng)建一個(gè)新的類(lèi)實(shí)現(xiàn)Comparator接口,不需要修改待比較類(lèi)的代碼,比如剛才待比較類(lèi)是Card,如果要是用Comparator這種實(shí)現(xiàn)方式的時(shí)候,就不用改Card的源碼

所以說(shuō)使用Comparable這種實(shí)現(xiàn)方式的時(shí)候,它的耦合性就更強(qiáng)一些,但這是我們不愿意看到的。

代碼實(shí)現(xiàn):基于Comparator接口類(lèi)的比較

package java2021_1018;

import java.util.Comparator;

//寫(xiě)一個(gè)輔助的類(lèi)Card(撲克牌-之前寫(xiě)過(guò))
class Card {
  //按照點(diǎn)數(shù)來(lái)比較
  public String rank;//點(diǎn)數(shù)
  public String suit;//花色
  //提供構(gòu)造方法

  public Card(String rank, String suit) {
      this.rank = rank;
      this.suit = suit;
  }
//寫(xiě)一個(gè)獲取值的方法,
 public int getValue() {
      //通過(guò)這個(gè)方法把String 類(lèi)型的rank(J  Q  K  A)變成數(shù)字點(diǎn)數(shù)11,12,13,14
      int value = 0;
      if("J".equals(rank)){
          value = 11;
      }else if("Q".equals(rank)){
          value = 12;
      }else if("K".equals(rank)){
          value = 13;
      }else if ("A".equals(rank)){
          value = 14;
      }else {
          value = Integer.parseInt(rank);//把字符串轉(zhuǎn)成數(shù)字
          //單獨(dú)處理J  Q  K  A,然后其他的2~10直接使用Integer.parseInt,把字符串轉(zhuǎn)換成整數(shù)。
      }
      return value;
  }
}z
//寫(xiě)一個(gè)CardComparator類(lèi)
class CatdComparator implements Comparator<Card>{//這里指定泛型參數(shù)就是針對(duì)誰(shuí)比較就寫(xiě)誰(shuí)
//實(shí)現(xiàn)一個(gè)compare方法
  @Override
  public int compare(Card o1, Card o2) {//compare方法里面有兩個(gè)參數(shù),類(lèi)型都是Card類(lèi)型
      //判斷特殊情況
      if(o1 == o2){//如果o1 和 o2身份相等
          return 0;
      }
      //判斷o1 、 o2是不是null的情況
      if(o1 == null){
          return -1;
      }
      if(o2 == null){
          return 1;
      }
      //比較值
      int value1 = o1.getValue();
      int value2 = o2.getValue();
      return value1-value2;
  }
}
public class TestCompare1 {
  public static void main(String[] args) {
      //寫(xiě)一個(gè)類(lèi)方法,在類(lèi)方法中構(gòu)造出這兩張牌
      Card a=new Card("3","♠");//第一張牌:a的點(diǎn)數(shù)為1,花色為黑桃
      Card b=new Card("K","♠");//第二張牌:b的點(diǎn)數(shù)為1,花色為黑桃
      Card c=a;
//Comparator的使用:先創(chuàng)建一個(gè)Comparator的實(shí)例
      CatdComparator comparator = new CatdComparator();
      System.out.println(comparator.compare(a,b));
  }
}

疑問(wèn):為什么有了Comparable還需要有一個(gè)Comparator呢?

1、因?yàn)镃omparable使用的時(shí)候必須要修改待比較類(lèi)的代碼,實(shí)際開(kāi)發(fā)中不是所有的類(lèi)都能修改源碼,(如果這個(gè)類(lèi)是庫(kù)或者是其他組的人提供的此時(shí)就不能隨便改人家的代碼,只能改自己的代碼)。

2、Comparable只能定義一種比較規(guī)則,Comparator可以定義多種比較規(guī)則(即可以實(shí)現(xiàn)多個(gè)Comparator類(lèi))。如:代碼中的CardComparator類(lèi),定義多份之后就可以有多種不同的比較規(guī)則了,然后就可以在不同的比較規(guī)則里面分別針對(duì)當(dāng)前的場(chǎng)景來(lái)自定制按照什么樣的方式來(lái)比較了。

 

三種比較方式對(duì)比

 

覆寫(xiě)的方法 說(shuō)明
Object.equals 因?yàn)樗蓄?lèi)都是繼承自 Object 的,所以直接覆寫(xiě)即可,不過(guò)只能比較相等與否
Comparable.compareTo 需要手動(dòng)實(shí)現(xiàn)接口,侵入性比較強(qiáng),但一旦實(shí)現(xiàn),每次用該類(lèi)都有順序,屬于內(nèi)部順序
Comparator.compare 需要實(shí)現(xiàn)一個(gè)比較器對(duì)象,對(duì)待比較類(lèi)的侵入性弱,但對(duì)算法代碼實(shí)現(xiàn)侵入性

到此這篇關(guān)于java中對(duì)象的比較equal、Comparble、Comparator的區(qū)別的文章就介紹到這了,更多相關(guān)java equal、Comparble、Comparator內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/m0_59157222/article/details/120945438

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 草馏社区最新1024 | xxxx成人| 99国产热| 武侠古典久久亚洲精品 | 成在线人免费 | xxx88视频在线观看 | 福利姬 magnet | 99久久国产综合精麻豆 | 久久青草免费91线频观看站街 | 放荡的女老板bd中文字幕 | 欧美亚洲另类在线观看 | 日本一级不卡一二三区免费 | 99热碰 | 亚洲AV 中文字幕 国产 欧美 | bl双性受乖调教改造身体 | 亚洲丰满女人ass硕大 | 手机在线观看国产精选免费 | 欧美人与牲动交xxx 欧美人妖另类性hd 欧美人人干 | 91四虎国自产在线播放线 | 亚洲国产韩国欧美在线不卡 | 能播放18xxx18女同 | 99热久久国产精品这里 | 青青青草国产线观 | 日本中文字幕在线视频站 | 亚洲欧美日韩国产精品影院 | 果冻传媒和91制片厂网站软件 | 日本高清中文字幕视频在线 | 俄罗斯年轻男同gay69 | 996热在线视频 | 久草热在线 | 日韩中文字幕网站 | 亚洲国产精品嫩草影院久久 | 蜜桃视频一区二区 | 欧美日韩在线一区二区三区 | 国产欧美成人不卡视频 | 国产亚洲精品美女2020久久 | free极度另类性欧美 | 日本精工厂网址 | 亚洲精品中文字幕第一区 | 龟甲情感超市全文阅读 小说 | 成年人视频在线免费看 |