我有一个名为 Work 的接口
public class interface Work {
boolean completeWork(Job j);
}
然后我有一个复合类
public class CompositeWork implements Work {
private Set<Work> childWork = new HashSet<>();
public boolean completeWork(Job j) {
return childWork.stream().allMatch(w -> w.completeWork(j));
}
public void addWork(Work w) {
childWork.add(w);
}
}
我有不同的工作类型如下:
public class EasyWork implements Work {
public boolean completeWork(Job j) {
<do some work>
}
}
public class HardWork implements Work {
private String id;
public Hardwork(String id) {
this.id = id;
}
public boolean completeWork(Job j) {
<do some work>
}
}
客户端填充复合工作类似这样的东西
public class Client {
public static void main(String[] args) {
CompositeWork workHolder = new CompositeWork();
workHolder.add(new EasyWork());
workHolder.add(new EasyWork());
workHolder.add(new HardWork("1"));
workHolder.add(new HardWork("2"));
}
}
为了在HashSet<>()
CompositeWork
中强制执行childWork
的唯一性,我在哪里实现hashcode()
和equals()
?
这是否发生在工作界面中?
复合作业类?
还是在EasyWork和HardWork中实现?
我们无法为您回答这个问题。这取决于您希望类的行为方式。
任何类的默认行为是不同的实例将相互比较不相等。如果您同意所有EasyWork
对象都是不同的,并且所有HardWork
对象都是不同的,即使它们包含相同的数据,那么您不需要执行任何操作。默认方法可能就足够了。
否则,您应该根据具体情况检查每个类:
-
如果您希望
HardWork
对象相等,如果它们具有相同的id
,另一方面,您需要覆盖equals()
并在HardWork
中hashCode()
。如果没有,请不要打扰。 -
同样,如果
EasyWork
对象应该彼此相等,那么您也需要在那里覆盖它们。如果没有,请不要打扰。 -
此外,如果您希望
CompositeWork
对象彼此相等,如果它们具有相同的子Set
,那么您也可以在那里覆盖它们。如果没有,请不要打扰。
因为你需要区分EasyWork
和HardWork
,所以你需要在这些类中实现这些方法。
这是一篇关于这个主题的好文章。
我看到了约翰·库格尔曼的回答,我几乎同意。几乎 - 因为有一件非常重要的事情经常被遗忘。如果你打算在像HashSet
这样的哈希依赖集合中使用EasyWork
和HardWork
对象,除了覆盖equals
和hashcode
之外,你还必须使你的类不可变。这意味着,
- 你的两个类都必须是
final
equals
和hashcode
方法将使用的字段必须是最终的。
解释
如果对象不是不可变的,那么您可以更改其某些字段,然后其hashCode
将返回新结果,然后由于哈希表中的位置错误,您将无法访问集合中的此对象。