今天自己翻了一下前面學(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()方法是把字符串按照字典順序進行排列倡蝙。那我們?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()方法不重寫也是可以的。