Reputation: 29
I have a class with many (about 100) fields. I want to implement hashCode()
and equals()
methods for these fields, is there any alternative to doing this manually?
Upvotes: 2
Views: 1743
Reputation: 912
While it's not a good practice to have an object with that many fields, sometimes legacy constraints trap you in a bad situation.
Regardless of size, I find the easiest way to override these methods is by using the Apache commons library. It uses reflection to generate the values from the instance and there are a number of ways to configure the results. I also never have to remember to regenerate the method if the fields update, unlike the eclipse generated methods.
@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);
}
Upvotes: 0
Reputation: 48864
Others have pointed out that an object this large is likely not a great pattern to follow, so I'll assume you know that already and have decided to proceed anyways. I'm also going to assume this object is (mostly) immutable, since implementing .hashCode()
for mutable objects is generally a bad plan (at the very least, you have to be careful about putting mutable objects in a HashSet
or as keys in a HashMap
).
If you have a class with a large number of fields you can avoid defining complex .hashCode()
, .equals()
, and .toString()
methods by taking advantage of existing functionality that does the same thing. An easy option is to construct a List
or Map
of your fields, and simply call the respective methods of that Collection
. You can even cache the return values of these functions, rather than hold onto the whole Collection
, if you want.
There are also many useful utilities to make these methods easier; there's way too many to list, but I'll try to call out a couple of particularly useful ones:
Objects.hash()
, Arrays.hashCode()
Arrays.equals()
Arrays.toString()
Hashing.combineOrdered()
and a whole batch of powerful hashing utilities.Iterables.elementsEqual()
MoreObjects.toStringHelper()
Additionally, you could use reflection to get all the fields in your object at runtime. This would be slower than a hard-coded implementation, but it would likely be faster to write. If you aren't overly concerned about speed, this is a good option.
Upvotes: 1
Reputation: 15729
There's no great answer. Here are a few suggestions. As others have commented, 100 fields are far too many. You best bet is to refactor the class. But, if you must keep it all together:
If so, you can use their built in hashCode() and equals() methods. (Or Guava etc. as pointed out by @dimo414)
If only a few of your fields are immutable, that will greatly simplify your hashCode()
code. And, more importantly, make it correct. :-)
If the answer is "extremely rarely", ask yourself if you could get away with using the basic Object equality (in effect, using ==)?
If so, you can sometimes use that String as an inefficient, but easy to code, hashCode() and equals(). e.g.:
public int hashCode() { return this.toString().hashCode(); }
public boolean equals(Object o) {
return (o instanceof MyClass) &&
(this.toString().equals(o.toString()));
}
Upvotes: 4
Reputation: 5023
I think It is better to use the eclipse functionality to generating code for hashCode()
and equals()
which does a pretty good job for implementing this methods.
Upvotes: 0