Google Guava / Equivalence /不同的equals()和hashCode()方法实现

时间:2011-11-01 17:19:05

标签: java guava

我希望能够在两个equals-Implementations之间切换,但我不确定Google Guava的Equivalence类是否可以提供此功能。假设我有两个equals方法equalsContent()和equalsKeys()或类似的东西我想以某种方式将equals方法委托给两个私有方法之一(对于两个hashCode方法也是如此)。

好吧,我不确定Equivalence抽象类和Equivalences类(静态方法)的用法是什么。

此外,您将如何实现上述所需的属性?我可以使用另一个简单地为值设置标志或枚举的方法,并使用两个抽象方法(equals(),hashCode())在枚举中实现两个equals和hash方法,并简单地调用enum.equals()或enum equals()和hashCode()方法中的.hashCode()。你觉得怎么样?

1 个答案:

答案 0 :(得分:7)

我认为枚举方法从面向对象的角度来看是有意义的,但它很危险。它可能会破坏equals()hashCode()契约(反身性,对称性和传递性)。例如,在同一Set中插入使用第一个等价策略的实例和使用第二个等价策略的实例会导致问题。

如果你想要不同的等价关系,你应该把它们放在你的课堂之外。 Equivalence允许您这样做:通过实现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中有更多信息。