这感觉像是一个非常基本的问题,但它困扰着我。我想得到两个集合之间的差异,但似乎我无法这样做,因为集合可能包含具有不同哈希和等于实现的对象。
为了给出我的问题的一个简化示例,假设我有一个由两个类实现的ifoo接口,将它们称为basicfoo和extendedfoo。它们都描述了同一个物理对象,但是extendedfoo包含了basicfoo所缺少的一些额外信息。基本上basicfoo描述了调用者感兴趣的物理对象,我最终将使用它在模型中查找适当的extendedfoo对象。如果一个basicfoo描述同一个物理对象,则可以认为它等于一个extendedfoo。
我有一种方法可以做这样的事情:
public void removeFooInModel(HashSet<IFoo> fooColection){
HashSet<Foo> fooInModel=Model.getFoo();
fooCollection.removeAll(fooInModel);
return;
}
我的问题是我认为它不会一直起作用。如果用户传入一个实际上包含BasicFoo对象的FooCollection,而my model.getFoo()方法返回一个实际上包含extendedFoo的集合,那么它们的equal和hashcode方法将不同(extendedFoo的状态要比equality的状态多得多)。尽管我对如何在两个对象之间映射相等和散列有非常清楚的理解,但似乎没有办法强制我的set对象使用这些知识。
我想知道的是,当我可能希望混合和匹配实现时,是否有任何方法可以方便地使用集合方法(比如removeall an contains)?
一种方法是使我的extendedfoo和basicfoo hashcode方法相同,只对ifoo接口中可用的状态进行散列,并通过比较ifoo getter方法使它们的相等方法比较不同类的任何ifoo对象。但是,如果我后来编写了一个扩展ifoo的foobar对象,我怎么能保证他们也编写了与我相同的hashcode方法,这样我的方法仍然可以与他们的类一起工作呢?
我可以很容易地解决我自己的问题,不使用一个集合在一个地方这是一个问题。然而,如果我需要哈希集提供的效率增益,其他人会认为“合适”的解决方案是什么?
最佳答案
不幸的是,您无法说服散列集将基本对象和扩展对象进行相等的比较,就好像它们都是基本对象一样。但是,您可以构建包含基本对象或扩展对象的包装器对象,并使用基本对象的比较方法来比较两者。
下面是一个可能的实现的草图:
class FooWrapper {
private final BasicFoo obj;
public FooWrapper(BasicFoo obj) {
this.obj = obj;
}
public BasicFoo getWrapped() {
return obj;
}
public int hashCode() {
// Compute the hash code the way the BasicFoo computes it
}
public boolean equals(Object other) {
// Compare the objects the way the BasicFoo does
}
}
现在您可以获取
BasicFoo
和ExtendedFoo
的混合集合,将它们包装在FooWrapper
中,并将它们放入散列集中。可以对集合执行操作,然后通过从包装器集合中展开单个BasicFoo
对象来获取结果。关于java - set.contains()和多态性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23400699/