2011-11-01 34 views
4

我希望能夠在兩個等於實現之間切換,但我不確定Google Guava的Equivalence類是否可以提供此功能。比方說,我有兩個equals方法equalsContent()和equalsKeys()或類似的東西,我想以某種方式將equals方法委託給兩個私有方法之一(對於兩個hashCode方法也是如此)。谷歌番石榴/等效/不同equals()和hashCode()方法的實現

嗯,我不知道Equivalence抽象類和Equivalences類(靜態方法)的用法是什麼。

此外,您將如何實現上述所需的屬性?我可以使用另一種方法,只需將一個標誌或枚舉設置爲該值,然後在兩個抽象方法(equals(),hashCode())的枚舉中實現兩個equals和hash方法,並簡單地調用enum.equals()或enum 。equals()和hashCode()方法中的.hashCode()。你怎麼看?

回答

7

我認爲枚舉方法從面向對象的角度來看是有意義的,但它很危險。它可能破壞equals()hashCode()合約(反射性,對稱性和傳遞性)。例如,在同一個Set中插入使用第一個等價策略的實例和使用第二個等價策略的實例會導致問題。

如果你想要不同的等價關係,你應該把這些關在課外。 Equivalence可以讓你做到這一點:通過實現等同性並覆蓋doHash()doEquivalent()方法來提取等價邏輯(equals()/ hashCode())。

然後,當您想要使用基於一個等值或另一個的Collection時,可以使用Equivalence.wrap()。例如,你可以通過做模擬一個IdentityHashSet

Set<Equivalence.Wrapper<String>> identityHashSet = Sets.newHashSet(); 

String a1 = "a"; 
String a2 = new String("a"); 
String b = "b"; 

identityHashSet.add(Equivalences.identity().wrap(a1)); 
identityHashSet.add(Equivalences.identity().wrap(a2)); 
identityHashSet.add(Equivalences.identity().wrap(a3)); 

// identityHashSet contains "a", "a", and "b" 
// a standard HashSet would only contain "a" and "b" 
// while a1 and a2 are equal according to String.equals(), they are different instances. 

當然,你可以使用ForwardingSet自動化包裝/解開你的元素。

還有更多的信息在this Guava issue

+1

不錯,謝謝,我甚至不知道包裝,但也許這可能是因爲我剛從r09更新Guava到10 ;-) – Johannes

+1

如何使用'ForwardingSet'來自動包裝/解包?如果您的班級擴展了'ForwardingSet >',則它不能執行'Set '。 – gdejohn

+0

好點。你需要自己實現轉發模式。儘管如此,'ForwardingSet'可能會有所幫助。 –