![](/img/trans.png)
[英]Why can we supply a Comparator to TreeSet but not something like Hasher to HashSet?
[英]TreeSet/TreeMap equivalent for HashSet/HashMap (custom hasher)
TreeSet
有一個帶比較器的構造函數,這意味着即使您存儲的對象本身不是Comparable
對象,您也可以提供自定義比較器。
是否有類似的無序集實現? (例如, HashSet<T>
的替代方法是采用“hasher”對象來計算對象T的equals()
和hashCode()
,這些對象可能與對象自己的實現不同?)
C ++ std::hash_set
為您提供了這個,只是想知道是否有適合Java的東西。
編輯:@Max提出了一個關於equals()
的良好技術觀點 - 足夠公平; 通過Map.containsKey()
對TreeMap
和HashMap
鍵Map.containsKey()
。 但是否有其他眾所周知的數據結構可以通過自定義哈希來組織?
不, Collections
規范不支持具有“hasher”對象。 您當然可以實現自己的集合來支持這一點,但另一種方法是將Hasher
視為您存儲在HashSet
的包裝對象。
Set<HasherWrapper<Foo>> set = new HashSet<HasherWrapper<Foo>>();
set.add(new HasherWrapper(foo));
...
然后包裝類看起來像:
private class HasherWrapper<T> {
T wrappedObject;
public HasherWrapper(T wrappedObject) {
this.wrappedObject = wrappedObject;
}
@Override
public int hashCode() {
// special hash code calculations go here
}
@Override
public boolean equals(Object obj) {
// special equals code calculations go here
}
}
標准庫中沒有這樣的實現,但它不會阻止您自己滾動。 這是我經常想要擁有的東西。
請參閱http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660 ,原因如下:
我們想避免復雜性。 在收集框架設計時,我們認真地接受了這個概念,但拒絕了它。 功率重量比似乎很低。 我們覺得平等是你想要的95%的時間; ==,4%; 和別的東西1%。 當等式謂詞不同時,為批量操作編寫合理的合同是非常棘手的。
不,沒有,也沒有規范。 而且,你誤解了TreeSet
使用它的Comparator
。
來自TreeSet Javadoc :
請注意,如果要正確實現Set接口,則由set維護的排序(無論是否提供顯式比較器)必須與equals一致。 (有關與equals一致的精確定義,請參閱Comparable或Comparator。)這是因為Set接口是根據equals操作定義的,但TreeSet實例使用compareTo(或compare)方法執行所有元素比較,因此從集合的角度來看,通過這種方法被認為相等的元素是相等的。 集合的行為即使其排序與equals不一致也是明確定義的; 它只是不遵守Set接口的一般合同。
當且僅當e1.compareTo(e2)== 0與c1的每個e1和e2的e1.equals(e2)具有相同的布爾值時,C類的自然排序被認為與equals一致。 null不是任何類的實例,並且即使e.equals(null)返回false,e.compareTo(null)也應拋出NullPointerException。
來自收藏夾javadoc :
boolean contains(Object o)
如果此collection包含指定的元素,則返回true。 更正式地,當且僅當此集合包含至少一個元素e時才返回true(o == null?e == null:o.equals(e))。
因此,通過規范,不能有任何類實現Collection<E>
接口並且完全依賴於某些外部Comparator樣式的對象來插入對象。 所有集合應使用Object
類的equals
方法來驗證對象是否已插入。
絕對沒有類似的東西, hashcode()
和equals()
定義了對象的屬性,不應該更改。 它們定義了使對象彼此相等的原因,並且這不應該從一個集合到另一個集合。 做你正在談論的唯一方法是子類化對象並編寫一個新的hashcode()
和equals()
,如果子類有一個應該添加的定義變量,這只會有意義。超類' hashcode()
和equals()
。 我知道這可能不是你的目標,但我希望這會有所幫助。 如果你想要更多地解釋你的推理,那么如果存在一個更好的解決方案可能會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.