我認爲枚舉方法從面向對象的角度來看是有意義的,但它很危險。它可能破壞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。
不錯,謝謝,我甚至不知道包裝,但也許這可能是因爲我剛從r09更新Guava到10 ;-) – Johannes
如何使用'ForwardingSet'來自動包裝/解包?如果您的班級擴展了'ForwardingSet>',則它不能執行'Set '。 –
gdejohn
好點。你需要自己實現轉發模式。儘管如此,'ForwardingSet'可能會有所幫助。 –