是否有可能在java中创建像Comparator,但用于实现自定义equals()和hashCode()

dhb*_*lah 51 java collections equals hashcode

我有一个对象数组,我想将它与另一个对象数组连接起来,除了具有相同id的对象.这些对象在系统中的许多地方使用,并且没有实现哈希码或等号.所以我不想要实现hashCode()equals(),因为我怕系统某处碰坏,其中所使用的对象,我不知道.

我想将所有对象放在一个集合中,但不知何故使对象使用自定义hashCode()equals().像自定义的东西Comparator,但对于平等.

Ste*_*n C 34

是的,可以做这样的事情.但它不允许您将对象放入HashMap,HashSet等.这是因为标准集合类期望关键对象提供equalshashCode方法.(这就是他们设计工作的方式......)

备择方案:

  1. 实现一个包含真实类实例的包装类,并提供自己的实现equalshashCode.

  2. 实现自己的基于哈希表的类,可以使用"hashable"对象来提供equals和hashcode功能.

  3. 咬紧牙关,实施equalshashCode覆盖相关课程.

事实上,第三种选择可能是最好的,因为你的代码库很可能需要使用一致的概念来确定这些对象是否相等.还有其他一些事情表明您的代码需要进行大修.例如,它当前正在使用对象数组而不是Set实现来表示显然应该是一个集合的事实.

另一方面,也许当前实现存在/是某些真实(或想象)的性能原因; 例如减少内存使用量.在这种情况下,您应该编写一堆辅助方法来执行操作,例如连接表示为数组的2个集合.

  • trove 库包含类似选项 #2 的内容,它们定义了一个 HashingStrategy 接口,可以在某些 HashMap 实例中使用。他们并没有完全概括这一点,而只是针对基于某些关键类的 HashMap 实现它。http://trove4j.sourceforge.net/javadocs/gnu/trove/strategy/HashingStrategy.html (2认同)

Kev*_*ion 13

当用户想要等价关系时,有90%的时间已经有了一个更简单的解决方案.你想只根据id去除一堆东西吗?你可以把它们全部放入一个地图中,用ids作为键,然后得到它的values()集合吗?

  • 如果你想选择键的哪些属性定义相等/散列并且你想把其他东西作为值,那么它不起作用.只有当某个键的重要属性是单数时,您的解决方案才有效,如果您想在哈希/等于中选择键使用的2+但不是所有重要属性,则它不起作用. (6认同)

Cra*_*lin 10

HashingStrategy是您正在寻找的概念.它是一个策略接口,允许您定义equals和hashcode的自定义实现.

public interface HashingStrategy<E>
{
    int computeHashCode(E object);
    boolean equals(E object1, E object2);
}
Run Code Online (Sandbox Code Playgroud)

正如其他人所指出的,你不能使用HashingStrategy内置HashSetHashMap.Eclipse Collections包含一个名为的set UnifiedSetWithHashingStrategy和一个名为的map UnifiedMapWithHashingStrategy.

我们来看一个例子.这是一个Data我们可以在一个简单的类中使用UnifiedSetWithHashingStrategy.

public class Data
{
    private final int id;

    public Data(int id)
    {
        this.id = id;
    }

    public int getId()
    {
        return id;
    }

    // No equals or hashcode
}
Run Code Online (Sandbox Code Playgroud)

以下是设置UnifiedSetWithHashingStrategy和使用它的方法.

java.util.Set<Data> set =
  new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(new Data(1)));

// contains returns true even without hashcode and equals
Assert.assertTrue(set.contains(new Data(1)));

// Second call to add() doesn't do anything and returns false
Assert.assertFalse(set.add(new Data(1)));
Run Code Online (Sandbox Code Playgroud)

为什么不用一个MapUnifiedSetWithHashingStrategy使用a的一半内存UnifiedMap,和a 的内存的四分之一HashMap.有时你没有方便的密钥,必须创建一个合成的密钥,就像一个元组.这会浪费更多的记忆.

我们如何执行查找?请记住,集合有contains(),但没有get().除了UnifiedSetWithHashingStrategy实现Pool之外MutableSet,所以它还实现了一种形式get().

注意:我是Eclipse Collections的提交者.