簡體   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