2012-10-06 103 views
8

我發佈了一些代碼here正確地解決了海報有問題。 OP想要刪除重複項目並將某些特殊項目列入列表頂部。我用TreeSet與一個特殊的Comparable類,他們包裝Locale他們正在與實現他們想要的。等於和與套比較

然後我開始思考......像你一樣......我被從compareTo方法返回0,而不是從equals實現返回true消除重複正如人們所需要做的正確指示重複在Set(來自Setdefinition)。

我不反對使用這種技術,但我使用什麼可能被認爲是未公開的功能?我是否安全地認爲今後做這種事情將繼續發揮作用?

+0

作爲Nurkiewicz先生所指出的看到,這是指定的行爲,所以它的安全。但我確實認爲這很令人驚訝! –

回答

17

看起來這是很好的JavaDoc of TreeSet(粗體礦)記載:

注意,排序由一組維護(無論是否提供了明確的比較器)必須符合等於如果是要正確實現接口Set。 (對於一致的精確定義與equals參見ComparableComparator)。這是因爲該Set接口在equals操作方面被定義,但TreeSet例如使用其compareTo(或比較)方法執行所有元件比較,所以從這個方法看,被這個方法認爲是相等的兩個要素是相等的。 即使它的排序與等號不一致,集合的行爲也是很好定義的;它只是不服從Set界面的總合同。

這裏是實現Comparable,但並不符合equals()所述only (?) JDK class的示例:

Set<BigDecimal> decimals = new HashSet<BigDecimal>(); 
decimals.add(new BigDecimal("42")); 
decimals.add(new BigDecimal("42.0")); 
decimals.add(new BigDecimal("42.00")); 
System.out.println(decimals); 

decimals在端部具有三個值,因爲4242.042.00是儘可能不相等如equals()被關注到。但是,如果您將HashSet替換爲TreeSet,則結果集僅包含1個項目(42--恰好是第一個添加的項目),因爲使用BigDecimal.compareTo()進行比較時,它們都被認爲是相等的。

這表明當使用與equals()不一致的類型時,TreeSet的方式爲「損壞」。它仍然正常工作,所有的操作都是明確的 - 它只是不服從Set類的合同 - 如果兩個類不是equal(),它們不被認爲是重複的。

+0

有趣的是,'ConcurrentSkipListSet'文檔中沒有這樣的註釋。 – OldCurmudgeon

+1

@OldCurmudgeon它實際上也在[SortedSet的javadoc]中指定(http://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html)(並且TreeSet和ConcurrentSkipListSet都實現了接口)。 – assylias

+0

所以它確實!接得好。 – OldCurmudgeon