繁体   English   中英

带有列表属性的 hashCode 和 equals

[英]hashCode and equals with a list property

我有一个 class在 equals/hashCode 中有一个 for 循环

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

}

我可以用版本 2 替换以前的 equals/hashCode 而不用担心正确性吗?

两个版本是否返回相同的结果?

总结一下:

对于典型的 List 实现,我们可以使用版本 2 而不是版本 1。

与此相关的另一个问题:

如果属性task不是List而是Stream版本 2是否也有效? Stream<Task> tasks )。

版本 2 可以正常工作,尽管它会返回略有不同的 hash 代码。

这取决于具体的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所做的。

另请注意,您的 hash 代码可能会在实现之间发生变化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM