2016-06-20 190 views
4

當我在看Java Object Ordering教程時,文章的最後一部分'比較器'讓我困惑了一下。排序集合的Java對象排序

通過定義類別Employee,該類別本身可以通過員工姓名進行比較,本教程不會顯示該類是否已覆蓋equals方法。然後它使用定製的Comparator,其中員工按照資歷進行排序以對員工列表進行排序,並且我可以理解。

然後教程解釋了爲什麼這將不作爲一個TreeSet收集整理等(一個SortedSet)工作,其原因是:

它產生的順序不是與equals兼容。這意味着這個比較器等同於equals方法沒有的對象。特別是,同一天僱用的任何兩名僱員將相當於平等。當你對一個List進行排序時,這並不重要;但是當您使用比較器來訂購已排序的集合時,這是致命的。如果使用此比較器將同一日期僱用的多個僱員插入到TreeSet中,則只會將第一個僱員添加到該集合中;第二個將被視爲重複的元素,將被忽略。

現在我很困惑,因爲我知道List允許重複的元素,同時Set不基於equals方法。所以我想知道教程何時說由Comparator生成的順序與等號不兼容,這是什麼意思?而且它還說'如果您使用此比較器將同一日期僱用的多個員工插入到TreeSet中,則只會將第一個員工添加到該集合中;第二個將被視爲重複的元素,將被忽略。「我不明白如何使用Comparator將影響使用原始equals方法。我認爲我的問題是如何使用compare和方法生產和分類TreeSet

回答

3

所以我不知道教程是什麼時候說比較器生成的順序與equals不兼容,這是什麼意思?

在此示例中,Comparator僅比較兩個Employee對象。此比較不以任何方式使用equalshashCode。記住這一點,當我們將這個Comparator傳遞給TreeSet時,該集合將認爲Comparator的任何結果都是0。因此,如果有任何Employee共享開始日期,則只會添加一個,因爲該集合認爲它們是平等的。

最後:

我想我的問題是,如何TreeSet中會產生在這種情況下排序,當比較和等於使用方法。

對於TreeSet,如果Comparator給出,它使用compare方法來確定對象的平等和訂貨。如果沒有給出Comparator,那麼該集合使用正在排序的對象的compareTo方法(它們必須實現Comparable)。

爲什麼Java規範聲稱,正在使用必須符合equalscompare/compareTo方法是因爲Set規範利用了equals,即使這種特定類型的Set,在TreeSet,使用比較,而不是原因。

如果您從某種方法實施中收到Set,則可以預計equals方法定義的Set中沒有對象的重複項。因爲TreeSet不使用此方法,所以開發人員必須小心確保比較方法與equals的結果相同。

+0

謝謝!現在我明白這是爲了保持它與'Set'接口的一致性,並且我看到了使用'equals()'方法的'contains()'方法。 –

2

TreeSet僅使用比較器,以確定是否兩個元素「相等」:

https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html

。注意,通過一組(無論是否提供了明確的比較器)維持的順序必須如果要正確實現Set接口,請與equals保持一致。 (請參閱Comparable或Comparator以獲得與equals一致的精確定義。)這是因爲Set接口是根據equals操作定義的,但TreeSet實例使用其compareTo(或compare)方法執行所有元素比較,所以兩個從這個方法看,被這個方法認爲是相等的元素是相等的。 即使排序與等號不一致,集合的行爲也是明確定義的;它只是不服從Set接口的總體合同。

這意味着比較應該返回0,當且僅當equals返回true,讓TreeSet中和其他集之間的一致的行爲,像HashSetHashSet確實使用equals和散列碼來確定兩個元素是否「相等」。

+0

我沒有完全得到你的答案,直到鋯石詳細闡述它。不過,非常感謝。 –