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

Joh*_*nes 4 java guava

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

好吧,我不知道Equivalence抽象类和Equivalences类(静态方法)的用法是什么.

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

Eti*_*veu 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.
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用ForwardingSet自动化元素的包装/展开.

这个番石榴问题有更多信息.