[英]comparator and comparable implementation in java
我知道這些接口用於集合中的排序對象。 但是,我懷疑它們之間的真正區別。 當您想將兩個對象與當前對象(本)進行比較時,我讀到的一個事實是使用可比性。
但是我的問題是,即使使用比較器,我們也可以比較相同的對象類型。
這里真的有什么區別。 我很困惑。 假設以下示例,
class Person implements Comparable<Person> {
private String firstName;
private String lastName;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int compareTo(Person anotherPerson){
int anotherPersonAge =anotherPerson.getAge();
return this.age - anotherPersonAge;
}
}
如果我使用比較器,我將擁有一個實現比較器的類,而不是this.age,它具有person.age。 那么,這里有什么不同?
public class LastNameComparator implements Comparator<Person> {
public int compare(Person person, Person anotherPerson) {
int age1 = person.getAge();
int age2 = anotherPerson.getAge();
return age1 - age2;
}
}
我不知道內部邏輯Collections.sort的使用。 如果是這樣,請說明以上幾點。
我也相信沒有必要返回-1,1或0。 上面的實現也有效吧? 我遇到的一個問題是,如果我們返回1,則列表如何根據升序或降序對項目進行排序? 我認為其差異要考慮並根據差異進行排序。
考慮可比文件
該接口對實現該接口的每個類的對象強加了總體排序。 此排序稱為類的自然排序,而該類的compareTo方法被稱為其自然比較方法。
和比較器
比較功能,對某些對象集合施加總體排序。 可以將比較器傳遞給排序方法(例如Collections.sort或Arrays.sort),以精確控制排序順序。 比較器還可以用於控制某些數據結構(例如排序集或排序映射)的順序,或為沒有自然順序的對象集合提供排序。
可Comparable
對象可以通過與另一個對象進行比較來確定其順序(自然順序),而Comparator
是知道如何比較兩個對象並確定其特定順序的對象。 這里的區別在於誰負責比較。
自然排序通過compareTo
強制使用已定義的順序,但是如果您想更改該順序,或者更糟的是,沒有已定義的比較邏輯怎么辦? 這是Comparator
派上用場的地方,因為您可以基於不同的比較來對集合進行排序,這些比較可以通過發出新的Comparator
器來動態切換,而不是一些討厭的邏輯,您應該告訴Comparable
對象“嘿,現在您按名稱排序而不是年齡”。
關於比較結果之間的差異,對每個對象進行檢查。 例如,采取三人隨着年齡的10
, 15
和20
。 15
與10
比較時返回-1
,與20
比較時返回-1
,定義了三個人的順序。
選擇適合您需求的方法。 如果您的比較邏輯是穩定的並且以后不會更改,則您可能希望擁有Comparable
對象,但是如果需要根據不同的條件對集合進行排序,則應該使用Comparator
。
快速掃描java.util.Collections javadocs提供了以下內容:
public static void sort(List list)-根據指定元素的自然順序將指定列表升序排序。 列表中的所有元素必須實現Comparable接口 。 此外,列表中的所有元素必須相互可比較(也就是說,對於列表中的任何元素e1和e2,e1.compareTo(e2)均不得拋出ClassCastException)。
public static void sort(List list,Comparator c)-根據指定比較器所誘導的順序對指定列表進行排序。 列表中的所有元素都必須使用指定的比較器進行相互比較 (即c.compare(e1,e2)不得對列表中的任何元素e1和e2拋出ClassCastException。
可以推斷出sort(List list)
然后使用Comparable接口, sort(List list, Comparator c)
使用比較器。
要回答您的最后一個問題,以您描述的方式使用這兩種方法沒有什么區別。擁有這兩種方法的目的是使您能夠以不同的方式比較對象,而不是以不同的方式使用不同的實現。
以這種方式考慮...您擁有具有一個整數的Class IntegerWrapper ,並且在該類中實現了Comparable 。 因此,當使用Collection.sort對它們進行排序時...它會為您提供升序的對象...
但是當您想更改此順序並希望降序時 ,則必須實現比較器以按所需順序對其進行排序...
在Java中,類型永遠只能實現一次接口,也就是說,您不能說
public class Foo implements Comparable<Foo>, Comparable<String> {}
這意味着Foo
的實例將始終以某種方式進行排序-您不能使排序在某種情況下的行為與另一種情況的行為不同。
的Comparator
,在另一方面,是獨立可排序的實例。 單個類型可以具有多個Comparator
(與完全相同的Comparable
相對)。 如果您需要某種排序,只需創建一個新的Comparator
。
編寫Comparator
對不同類型的實例進行排序也很容易-使用Comparable
很難做到這一點,因為所有涉及的實例都必須彼此了解:任何實例都可以將其他實例作為compareTo()
參數,並且實現一些通用接口等
當有人使用Comparable接口時,我總是會感到害怕,因為它幾乎總是錯誤的選擇。 可比用於定義自然順序,而不用於排序。 Java知道必須滿足的equals-hashcode合同。 大多數開發人員都知道。 但是還有另外一個重要的合同:可比合同。
這意味着:
a.equals(b)<==> a.compareTo(b)== 0
在您的示例中,您不能在一個TreeSet中擁有兩個具有相同年齡的不同人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.