【Java】Comparable & Comparator

今天自己翻了一下前面學(xué)習(xí)的知識,突然間看到這個話題,回想了一下,感覺自己對Comparable和Comparator的理解印象不是很深了。就打算寫一下這一篇博客,重溫一下好了。之后自己再不明確的時候,也可以來翻一下。


區(qū)別

  • Comparable & Comparator 都是用來實現(xiàn)集合中的元素比較、排序的。其中Comparable是在集合內(nèi)部定義的方法實現(xiàn)的排序,Comparator是在集合外部絲線的排序。所以,要想實現(xiàn)排序的功能,就需要在集合內(nèi)實現(xiàn)Comparable接口的方法(也就是重寫compareTo()方法)或者在集合外實現(xiàn)Comparator接口的方法(也就是重寫compare()方法)。

  • Comparable位于包java.lang下,Comparator位于包java.util下。

  • Comparable是一個類本身就已經(jīng)支持比較所需要實現(xiàn)的接口(如String、Integer自己就可以完成比較大小的操作,因為已經(jīng)實現(xiàn)了Comparable接口)。自定義的類需要實現(xiàn)Comparable并把實例對象加入List集合中后才可以排序。而Comparator,我們可以稱之為比較器。當(dāng)這個類不支持自身比較或者自比較的方法不能滿足我的要求的時候,我們可以寫一個比較器來完成兩個對象之間的大小比較。可以說一個是自己完成比較,另外一個是通過外部的來程序完成比較。

用Comparator是策略模式(Strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變他的行為。

那就有一個疑問了,為什么需要存在Comparator呢?我們都用Comparable不就好了嗎?哈哈。這里我們就有一個場景啦。比如對于字符串的排序,String類已經(jīng)實現(xiàn)了Comparable接口,它的compareTo()方法是把字符串按照字典順序進(jìn)行排列。那我們?nèi)绻胍址凑臻L度來排序呢?String類是不允許我們修改它而且是一個final類(最終類)是不能被繼承的,也就是說我們不能去重寫compareTo()方法。那么我們就必須實現(xiàn)Comparator接口,生成一個比較器。這樣的解釋應(yīng)該挺明白了吧。

Comparable示例程序

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StudentComparable implements Comparable<StudentComparable> {    
  private String name;    
  private int age;    

  public StudentComparable(String name, int age) {        
    this.name = name;        
    this.age = age;    
  }    

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

  public void setAge(int age) {        
    this.age = age;    
  }    

  public String getName() {        
    return name;    
  }    

  public int getAge() {        
    return age;    
  }    

  @Override    
  public boolean equals(Object o) {        
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }        

    StudentComparable that = (StudentComparable) o;        
    if (getAge() != that.getAge()) {
      return false;
    }        

    return getName() != null ? getName().equals(that.getName()) : that.getName() == null;    
  }    

  @Override    
  public int hashCode() {        
    int result = getName() != null ? getName().hashCode() : 0;        
    result = 31 * result + getAge();        
    return result;    
  }    

  @Override    
  public int compareTo(StudentComparable o) {        
    if (this.name.compareTo(o.getName()) > 0) {            
      return 1;        
    }else if (this.name.compareTo(o.getName()) < 0) {            
      return -1;        
    }        
    return 0;    
  }    

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

  public static void main(String[] args) {        
    List<StudentComparable> list = new ArrayList<>();        
    list.add(new StudentComparable("Jack", 16));        
    list.add(new StudentComparable("Mike", 25));        
    list.add(new StudentComparable("Summer", 17));        
    list.add(new StudentComparable("Bob", 19));        
    Collections.sort(list);        
    for (StudentComparable stu : list) {            
      System.out.println(stu);        
    }    
  }
}

Comparator示例代碼

import java.util.*;

class A implements Comparator<String> {    
  @Override    
  public int compare(String s1, String s2) {        
    int len1 = s1.length();        
    int len2 = s2.length();        
    if (len1 > len2) {            
      return 1;        
    }else if (len1 < len2) {            
      return -1;        
    }else {            
      return 0;        
    }    
  }
}

public class ComparatorTest {    
  public static void main(String[] args) {        
    List<String> list = new ArrayList<>();        
    list.add("cat");        
    list.add("fish");        
    list.add("dog");        
    list.add("panda");        
    Collections.sort(list, new A());        
    System.out.println(list);    
  }
}

注意

  • 在Comparable接口的實現(xiàn)類里,我們要必須重寫compareTo()方法,看需求是否需要重寫hashCode()方法和equals()方法 (有關(guān)hashCode()和equals()的意義和用法,詳見我的另一篇文章(待定))。

  • 在Comparator接口的實現(xiàn)類里,我們必須重寫compare()方法,看需求是否需要重寫hashCode()方法和equals()方法 。

  • 其實上述的hashCode()方法和equals()方法不重寫也是可以的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,872評論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,823評論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,658評論 0 3
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,468評論 0 16
  • 好像每次都是這樣,沒有例外。在我們最需要有一個人去依靠的時候,往往到最后都是自己一個人挺過去。 ??? 這是為什么...
    A分享閱讀 550評論 1 1

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