hashCode и равно со свойством списка - PullRequest
0 голосов
/ 01 октября 2019

У меня есть класс с циклом в пределах 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);

    }
}

У меня есть эта версия (версия 2) из equals / hashCode, который короче и быстрее:

@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);

}

Можно ли заменить прежний equals / hashCode версией 2, не беспокоясь о правильности?

Обе версии возвращают один и тот же результат?

Подводя итог:

для типичной реализации List, мы можем использовать версию 2 вместо версии 1.

Еще один вопрос, связанный с этим:

Будет ли версия 2 также действительным, если свойство task не является Listно Stream? (Stream<Task> tasks).

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Это зависит от конкретной реализации List. Давайте посмотрим, что делает Object.equals:

public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

Итак, он проверяет пару тривиальных случаев, затем вызывает a.equals(b), что означает, что он вызовет метод equals вашего списка. Но если вы используете какой-либо пользовательский List или просто какой-то список, который не сравнивает элементы один за другим, тогда реализация двух будет отличаться.

Для любой вменяемой реализации, equals должен повторятьсяпо элементам и сравните каждый, используя equals. Это то, что AbstractList делает.

Также обратите внимание, что ваш хэш-код, вероятно, будет меняться между реализациями.

1 голос
/ 01 октября 2019

Версия 2 будет работать очень хорошо, хотя и будет возвращать немного другие хэш-коды.

...