簡體   English   中英

HashSet / HashMap等效的TreeSet / TreeMap(自定義哈希)

[英]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()TreeMapHashMapMap.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接口的一般合同。

來自Comparable javadoc

當且僅當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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM