我有一个有很多(大约100个)字段的课程。我想为这些字段实施hashCode()
和equals()
方法,是否可以手动执行此操作?
答案 0 :(得分:4)
没有好的答案。以下是一些建议。正如其他人评论的那样,100个领域太多了。你最好的选择是重构课程。但是,如果你必须把它们放在一起:
如果是这样,您可以使用他们内置的hashCode()和equals()方法。 (或@ dimo414指出的番石榴等)
如果只有少数字段是不可变的,那么这将大大简化您的hashCode()
代码。而且,更重要的是,使其正确。 : - )
如果答案是"非常罕见",问问自己是否可以使用基本的对象相等(实际上,使用==)?
如果是这样,您可以有时使用该String作为低效但易于编码的hashCode()和equals()。 e.g:
public int hashCode() { return this.toString().hashCode(); }
public boolean equals(Object o) {
return (o instanceof MyClass) &&
(this.toString().equals(o.toString()));
}
答案 1 :(得分:1)
其他人已经指出,这么大的物体可能不是一个很好的模式,所以我假设你已经知道并且已经决定继续进行。我也会假设这个对象(大部分)是不可变的,因为为可变对象实现.hashCode()
通常是一个糟糕的计划(至少,你必须小心将可变对象放在{ {1}}或HashSet
中的键。
如果您有一个包含大量字段的类,则可以通过利用执行相同操作的现有功能来避免定义复杂的HashMap
,.hashCode()
和.equals()
方法。一个简单的选择是构建字段的.toString()
或List
,并简单地调用Map
的相应方法。如果需要,您甚至可以缓存这些函数的返回值,而不是保留整个Collection
。
还有许多有用的实用程序可以使这些方法更容易;有太多的东西要列出,但我会试着说出一些特别有用的东西:
Objects.hash()
,Arrays.hashCode()
Arrays.equals()
Arrays.toString()
Hashing.combineOrdered()
和一大批强大的hashing utilities。Iterables.elementsEqual()
MoreObjects.toStringHelper()
此外,您可以在运行时在对象中use reflection to get all the fields。这比硬编码实现要慢,但编写起来可能会更快。如果你不太关心速度,这是一个不错的选择。
答案 2 :(得分:0)
我认为最好使用 eclipse功能为hashCode()
和equals()
生成代码,这对于实现此方法非常有用。
答案 3 :(得分:0)
虽然拥有一个包含许多字段的对象并不是一个好习惯,但有时候遗留约束会让你陷入困境。
无论大小如何,我发现覆盖这些方法的最简单方法是使用Apache commons库。它使用反射从实例生成值,并且有许多方法可以配置结果。如果字段更新,我也永远不必记住重新生成方法,这与eclipse生成的方法不同。
@Override
public final boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if(obj != null && obj.getClass() == this.getClass()) {
return EqualsBuilder.relectionEquals(this, obj, true);
}
return false;
}
@Override
public final int hashCode() {
return HashCodeBuilder.relectionHashCode(this);
}
@Override
public final String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}