欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java Comparable 和 Comparator 的詳解及區(qū)別

 更新時(shí)間:2016年12月01日 09:53:03   作者:張拭心  
這篇文章主要介紹了Java Comparable 和 Comparator 的詳解及區(qū)別的相關(guān)資料,Comparable 自然排序和Comparator 定制排序的實(shí)例,需要的朋友可以參考下

Java Comparable 和 Comparator 的詳解及區(qū)別

Java 中為我們提供了兩種比較機(jī)制:Comparable 和 Comparator,他們之間有什么區(qū)別呢?今天來(lái)了解一下。

Comparable 自然排序

Comparable 在 java.lang 包下,是一個(gè)接口,內(nèi)部只有一個(gè)方法 compareTo():

public interface Comparable<T> {
  public int compareTo(T o);
}

Comparable 可以讓實(shí)現(xiàn)它的類的對(duì)象進(jìn)行比較,具體的比較規(guī)則是按照 compareTo 方法中的規(guī)則進(jìn)行。這種順序稱為 自然順序。

compareTo 方法的返回值有三種情況:

  1. e1.compareTo(e2) > 0 即 e1 > e2
  2. e1.compareTo(e2) = 0 即 e1 = e2
  3. e1.compareTo(e2) < 0 即 e1 < e2

注意:

1.由于 null 不是一個(gè)類,也不是一個(gè)對(duì)象,因此在重寫(xiě) compareTo 方法時(shí)應(yīng)該注意 e.compareTo(null) 的情況,即使 e.equals(null) 返回 false,compareTo 方法也應(yīng)該主動(dòng)拋出一個(gè)空指針異常 NullPointerException。

2.Comparable 實(shí)現(xiàn)類重寫(xiě) compareTo 方法時(shí)一般要求 e1.compareTo(e2) == 0 的結(jié)果要和 e1.equals(e2) 一致。這樣將來(lái)使用 SortedSet 等根據(jù)類的自然排序進(jìn)行排序的集合容器時(shí)可以保證保存的數(shù)據(jù)的順序和想象中一致。
有人可能好奇上面的第二點(diǎn)如果違反了會(huì)怎樣呢?

舉個(gè)例子,如果你往一個(gè) SortedSet 中先后添加兩個(gè)對(duì)象 a 和 b,a b 滿足 (!a.equals(b) && a.compareTo(b) == 0),同時(shí)也沒(méi)有另外指定個(gè) Comparator,那當(dāng)你添加完 a 再添加 b 時(shí)會(huì)添加失敗返回 false, SortedSet 的 size 也不會(huì)增加,因?yàn)樵?SortedSet 看來(lái)它們是相同的,而 SortedSet 中是不允許重復(fù)的。

實(shí)際上所有實(shí)現(xiàn)了 Comparable 接口的 Java 核心類的結(jié)果都和 equlas 方法保持一致。
實(shí)現(xiàn)了 Comparable 接口的 List 或則數(shù)組可以使用 Collections.sort() 或者 Arrays.sort() 方法進(jìn)行排序。

實(shí)現(xiàn)了 Comparable 接口的對(duì)象才能夠直接被用作 SortedMap (SortedSet) 的 key,要不然得在外邊指定 Comparator 排序規(guī)則。

因此自己定義的類如果想要使用有序的集合類,需要實(shí)現(xiàn) Comparable 接口,比如:

**
 * description: 測(cè)試用的實(shí)體類 書(shū), 實(shí)現(xiàn)了 Comparable 接口,自然排序
 * <br/>
 * author: shixinzhang
 * <br/>
 * data: 10/5/2016
 */
public class BookBean implements Serializable, Comparable {
  private String name;
  private int count;


  public BookBean(String name, int count) {
    this.name = name;
    this.count = count;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getCount() {
    return count;
  }

  public void setCount(int count) {
    this.count = count;
  }

  /**
   * 重寫(xiě) equals
   * @param o
   * @return
   */
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof BookBean)) return false;

    BookBean bean = (BookBean) o;

    if (getCount() != bean.getCount()) return false;
    return getName().equals(bean.getName());

  }

  /**
   * 重寫(xiě) hashCode 的計(jì)算方法
   * 根據(jù)所有屬性進(jìn)行 迭代計(jì)算,避免重復(fù)
   * 計(jì)算 hashCode 時(shí) 計(jì)算因子 31 見(jiàn)得很多,是一個(gè)質(zhì)數(shù),不能再被除
   * @return
   */
  @Override
  public int hashCode() {
    //調(diào)用 String 的 hashCode(), 唯一表示一個(gè)字符串內(nèi)容
    int result = getName().hashCode();
    //乘以 31, 再加上 count
    result = 31 * result + getCount();
    return result;
  }

  @Override
  public String toString() {
    return "BookBean{" +
        "name='" + name + '\'' +
        ", count=" + count +
        '}';
  }

  /**
   * 當(dāng)向 TreeSet 中添加 BookBean 時(shí),會(huì)調(diào)用這個(gè)方法進(jìn)行排序
   * @param another
   * @return
   */
  @Override
  public int compareTo(Object another) {
    if (another instanceof BookBean){
      BookBean anotherBook = (BookBean) another;
      int result;

      //比如這里按照書(shū)價(jià)排序
      result = getCount() - anotherBook.getCount();   

     //或者按照 String 的比較順序
     //result = getName().compareTo(anotherBook.getName());

      if (result == 0){  //當(dāng)書(shū)價(jià)一致時(shí),再對(duì)比書(shū)名。 保證所有屬性比較一遍
        result = getName().compareTo(anotherBook.getName());
      }
      return result;
    }
    // 一樣就返回 0
    return 0;
  }

上述代碼還重寫(xiě)了 equlas(), hashCode() 方法,自定義的類想要進(jìn)行比較時(shí)都要重寫(xiě)這些方法。

后面重寫(xiě) compareTo 時(shí),要判斷某個(gè)相同時(shí)對(duì)比下一個(gè)屬性,把所有屬性都比較一次。

Comparable 接口屬于 Java 集合框架的一部分。

Comparator 定制排序

Comparator 在 java.util 包下,也是一個(gè)接口,JDK 1.8 以前只有兩個(gè)方法:

public interface Comparator<T> {

  public int compare(T lhs, T rhs);

  public boolean equals(Object object);
}

JDK 1.8 以后又新增了很多方法:

基本上都是跟 Function 相關(guān)的,這里暫不介紹 1.8 新增的。

從上面內(nèi)容可知使用自然排序需要類實(shí)現(xiàn) Comparable,并且在內(nèi)部重寫(xiě) comparaTo 方法。

而 Comparator 則是在外部制定排序規(guī)則,然后作為排序策略參數(shù)傳遞給某些類,比如 Collections.sort(), Arrays.sort(), 或者一些內(nèi)部有序的集合(比如 SortedSet,SortedMap 等)。

使用方式主要分三步:

1.創(chuàng)建一個(gè) Comparator 接口的實(shí)現(xiàn)類,并賦值給一個(gè)對(duì)象

在 compare 方法中針對(duì)自定義類寫(xiě)排序規(guī)則

2.將 Comparator 對(duì)象作為參數(shù)傳遞給 排序類的某個(gè)方法

3.向排序類中添加 compare 方法中使用的自定義類

舉個(gè)例子:

 // 1.創(chuàng)建一個(gè)實(shí)現(xiàn) Comparator 接口的對(duì)象
    Comparator comparator = new Comparator() {
      @Override
      public int compare(Object object1, Object object2) {
        if (object1 instanceof NewBookBean && object2 instanceof NewBookBean){
          NewBookBean newBookBean = (NewBookBean) object1;
          NewBookBean newBookBean1 = (NewBookBean) object2;
          //具體比較方法參照 自然排序的 compareTo 方法,這里只舉個(gè)栗子
          return newBookBean.getCount() - newBookBean1.getCount();
        }
        return 0;
      }
    };

    //2.將此對(duì)象作為形參傳遞給 TreeSet 的構(gòu)造器中
    TreeSet treeSet = new TreeSet(comparator);

    //3.向 TreeSet 中添加 步驟 1 中 compare 方法中設(shè)計(jì)的類的對(duì)象
    treeSet.add(new NewBookBean("A",34));
    treeSet.add(new NewBookBean("S",1));
    treeSet.add( new NewBookBean("V",46));
    treeSet.add( new NewBookBean("Q",26));

其實(shí)可以看到,Comparator 的使用是一種策略模式,不熟悉策略模式的同學(xué)可以點(diǎn)這里查看: 策略模式:網(wǎng)絡(luò)小說(shuō)的固定套路 了解。

排序類中持有一個(gè) Comparator 接口的引用:

Comparator<? super K> comparator;
而我們可以傳入各種自定義排序規(guī)則的 Comparator 實(shí)現(xiàn)類,對(duì)同樣的類制定不同的排序策略。

總結(jié)

Java 中的兩種排序方式:

Comparable 自然排序。(實(shí)體類實(shí)現(xiàn))
Comparator 是定制排序。(無(wú)法修改實(shí)體類時(shí),直接在調(diào)用方創(chuàng)建)

同時(shí)存在時(shí)采用 Comparator(定制排序)的規(guī)則進(jìn)行比較。

對(duì)于一些普通的數(shù)據(jù)類型(比如 String, Integer, Double…),它們默認(rèn)實(shí)現(xiàn)了Comparable 接口,實(shí)現(xiàn)了 compareTo 方法,我們可以直接使用。

而對(duì)于一些自定義類,它們可能在不同情況下需要實(shí)現(xiàn)不同的比較策略,我們可以新創(chuàng)建 Comparator 接口,然后使用特定的 Comparator 實(shí)現(xiàn)進(jìn)行比較。

這就是 Comparable 和 Comparator 的區(qū)別。

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • 關(guān)于springBoot yml文件的list讀取問(wèn)題總結(jié)(親測(cè))

    關(guān)于springBoot yml文件的list讀取問(wèn)題總結(jié)(親測(cè))

    這篇文章主要介紹了關(guān)于springBoot yml文件的list讀取問(wèn)題總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot模塊里面調(diào)用另外一個(gè)模塊的方法實(shí)現(xiàn)

    springboot模塊里面調(diào)用另外一個(gè)模塊的方法實(shí)現(xiàn)

    在Spring-Boot項(xiàng)目開(kāi)發(fā)中,存在著本模塊的代碼需要訪問(wèn)外面模塊接口,本文就來(lái)介紹一下springboot模塊里面調(diào)用另外一個(gè)模塊的方法實(shí)現(xiàn),感興趣的可以了解一下
    2023-11-11
  • Fluent Mybatis零xml配置實(shí)現(xiàn)復(fù)雜嵌套查詢

    Fluent Mybatis零xml配置實(shí)現(xiàn)復(fù)雜嵌套查詢

    本文主要介紹了Fluent Mybatis零xml配置實(shí)現(xiàn)復(fù)雜嵌套查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java Predicate及Consumer接口函數(shù)代碼實(shí)現(xiàn)解析

    Java Predicate及Consumer接口函數(shù)代碼實(shí)現(xiàn)解析

    這篇文章主要介紹了Java Predicate及Consumer接口函數(shù)代碼實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • IDEA修改生成jar包名字的兩種方法實(shí)現(xiàn)

    IDEA修改生成jar包名字的兩種方法實(shí)現(xiàn)

    本文主要介紹了IDEA修改生成jar包名字的兩種方法實(shí)現(xiàn),通過(guò)簡(jiǎn)單的步驟,您可以修改項(xiàng)目名稱并在打包時(shí)使用新的名稱,具有一定的參考價(jià)值,感興趣的可以了解下
    2023-08-08
  • Java?精煉解讀數(shù)據(jù)結(jié)構(gòu)的順序表如何操作

    Java?精煉解讀數(shù)據(jù)結(jié)構(gòu)的順序表如何操作

    程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要?jiǎng)?chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個(gè)數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示
    2022-03-03
  • 利用Java快速查找21位花朵數(shù)示例代碼

    利用Java快速查找21位花朵數(shù)示例代碼

    這篇文章主要給大家介紹了關(guān)于利用Java快速查找21位花朵數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • Mybatis多參數(shù)及實(shí)體對(duì)象傳遞實(shí)例講解

    Mybatis多參數(shù)及實(shí)體對(duì)象傳遞實(shí)例講解

    在使用Mybatis的時(shí)候,經(jīng)常會(huì)有各種各樣的參數(shù)傳遞,不同類型,不同個(gè)數(shù)的參數(shù),下面小編通過(guò)例子給大家講解下Mybatis多參數(shù)及實(shí)體對(duì)象傳遞,一起看看吧
    2016-12-12
  • SpringBoot關(guān)于自動(dòng)注入mapper為空的坑及解決

    SpringBoot關(guān)于自動(dòng)注入mapper為空的坑及解決

    這篇文章主要介紹了SpringBoot關(guān)于自動(dòng)注入mapper為空的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java中Shiro安全框架的權(quán)限管理

    Java中Shiro安全框架的權(quán)限管理

    這篇文章主要介紹了Java中Shiro安全框架的權(quán)限管理,Apache?Shiro是Java的一個(gè)安全框架,Shiro可以非常容易的開(kāi)發(fā)出足夠好的應(yīng)用,其不僅可以用在JavaSE環(huán)境,也可以用在JavaEE環(huán)境,需要的朋友可以參考下
    2023-08-08

最新評(píng)論