Reputation: 5698
I have a class with a for-loop within the equals/hashCode:
class User {
private List<Task> tasks;
private ZonedDateTime date;
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + (date != null ? date() : 0);
for (var task : tasks) {
hash = 31 * hash + task.hashCode();
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final User other = (User) obj;
if (tasks.size() != other.tasks.size()) return false;
// needed?
for (int i = 0; i < tasks.size(); i++) {
if (!tasks.get(i).equals(other.tasks.get(i))) {
return false;
}
}
return Objects.equals(timeStamp, other.timeStamp) && Objects.equals(tasks, other. tasks);
}
}
I am used to have this version (version 2) of equals/hashCode, which is shorter and faster:
@Override
public int hashCode() {
return Objects.hash(date, tasks);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final User other = (User) obj;
return Objects.equals(timeStamp, other.timeStamp) && Objects.equals(tasks, other. tasks);
}
Can I replace the former equals/hashCode with the version 2 without worrying about correctness?
Are both versions return the same result?
To sum up:
for typcial List implementation we can use version 2 instead of version 1.
One additional question related to this:
Will version 2 be also valid, if the property task
is not a List
but a Stream
? (Stream<Task> tasks
).
Upvotes: 2
Views: 2409
Reputation: 30335
It depends on the specific List
implementation.
Let's look at what Object.equals
does:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
So it checks for a couple of trivial cases, then calls a.equals(b)
, which means that it will call the equals
method of your list. But if you're using some custom List
or just some list that doesn't compare the elements one by one, then the two implementation will be different.
For any sane implementation, equals
should iterate over the elements and compare each one using equals
. This is what AbstractList
does.
Also note that your hash code will probably change between implementations.
Upvotes: 1
Reputation: 198471
Version 2 will work just fine, though it will return slightly different hash codes.
Upvotes: 1