簡體   English   中英

我需要實現hashCode()和equals()方法嗎?

[英]Do I need to implement hashCode() and equals() methods?

如果我有一個地圖和一個對象作為地圖鍵,是默認的哈希和等於方法嗎?

class EventInfo{

    private String name;
    private Map<String, Integer> info
 }

然后我想創建一個地圖:

Map<EventInfo, String> map = new HashMap<EventInfo, String>();

我是否必須顯式實現hashCode()和equals()? 謝謝。

是的你是。 HashMap通過計算密鑰的哈希碼並將其用作基點來工作。 如果hashCode函數沒有被覆蓋(由你),那么它將使用內存地址, equals將與==相同。

如果您在Eclipse中,它將為您生成它們。 單擊Source菜單→ Generate hashCode()和equals()

如果您沒有Eclipse,那么這里應該有一些。 (我在Eclipse中生成了這些,如上所述。)

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((info == null) ? 0 : info.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (!(obj instanceof EventInfo)) {
        return false;
    }
    EventInfo other = (EventInfo) obj;
    if (info == null) {
        if (other.info != null) {
            return false;
        }
    } else if (!info.equals(other.info)) {
        return false;
    }
    if (name == null) {
        if (other.name != null) {
            return false;
        }
    } else if (!name.equals(other.name)) {
        return false;
    }
    return true;
}

是的,你需要它們,否則你將無法比較兩個EventInfo(你的地圖將不起作用)。

嚴格來說,沒有。 hashCode()和equals()的默認實現將產生應該起作用的結果。 請參閱http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()

我的理解是hashCode()的默認實現通過在內存中獲取對象的地址並轉換為整數來工作,並且只有當兩個對象實際上是同一個對象時,equals()的默認實現才返回true。

在實踐中,您可以(而且應該)改進這兩種實現。 例如,兩種方法都應該忽略不重要的對象成員。 此外,equals()可能希望以遞歸方式比較對象中的引用。

在您的特定情況下,如果兩個對象引用相同的字符串或兩個字符串相等兩個映射相同或相等則可以將equals()定義為true。 我認為WChargin給你很好的實現。

取決於你想要發生什么。 如果具有相同nameinfo兩個不同的EventInfo實例應該導致兩個不同的鍵,那么您不需要實現equalshashCode

所以

EventInfo info1 = new EventInfo();
info1.setName("myname");
info1.setInfo(null);
EventInfo info2 = new EventInfo();
info2.setName("myname");
info2.setInfo(null);

info1.equals(info2)將返回false和info1.hashCode()將不同的值返回info2.hashCode()

因此,當您將它們添加到地圖時:

map.put(info1, "test1");
map.put(info2, "test2");

你會有兩個不同的條目。

現在,這可能是期望的行為。 例如,如果您的EventInfo正在收集不同的事件,那么具有相同數據的兩個不同事件可能希望成為兩個不同的條目。

equalshashCode合約也適用於Set

例如,如果您的活動信息包含鼠標點擊,那么您可能希望最終得到:

Set<EventInfo> collectedEvents = new HashSet<EventInfo>();
collectedEvents.add(info1);
collectedEvents.add(info2);

2個收集的活動,而不僅僅是1 ...

希望我在這里有意義......

編輯:

但是,如果上面的set和map應該只包含一個條目,那么你可以使用apache commons EqualsBuilderHashCodeBuilder來簡化equalshashCode的實現:

@Override
public boolean equals(Object obj) {
    if (obj instanceof EventInfo) {
        EventInfo other = (EventInfo) obj;
        EqualsBuilder builder = new EqualsBuilder();
        builder.append(name, other.name);
        builder.append(info, other.info);
        return builder.isEquals();
    }
    return false;
}

@Override
public int hashCode() {
    HashCodeBuilder builder = new HashCodeBuilder();
    builder.append(name);
    builder.append(info);
    return builder.toHashCode();
}

EDIT2:

如果兩個EventInfo實例具有相同的名稱,也可能是合適的,例如,如果name是某個唯一標識符(我知道它與您的特定對象有點牽強,但我在這里進行了概括)。 ..)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM