簡體   English   中英

編譯器或JVM是否強制執行hashCode / equals合同?

[英]Does the compiler, or JVM, enforce the hashCode/equals contract?

我作為鍵存儲在HashMap中的對象將覆蓋equals(),但不會覆蓋hashCode(); 當我在地圖上放置一個對象時,equals()方法沒有被調用。 如果我還重寫hashCode(),則調用equals()方法。 這是為什么?

為什么無論我是否重寫hashCode(),我都無法利用自定義的equals方法來防止向地圖添加對象?

謝謝。

package package1;

public class PlayWithHash {

    public static void main(String [] args){
        java.util.Map<Cat, Cat> map = new java.util.HashMap<Cat, Cat>();
        map.put(new Cat(), new Cat());
        map.put(new Cat(), new Cat());
        System.out.println("hashmap size = " + map.size());
    }
}

class Cat{
    @Override
    public int hashCode(){
        return 1;
    }
    @Override
    public boolean equals(Object d){
        Cat c = (Cat) d;
        if(this.hashCode() == c.hashCode()){
            return true;
        }
        return false;
    }
}

如果對hashCode()進行注釋,則size = 2,否則為size = 1。

我在想,如果我不重寫hashCode(),而是使用Object的hashCode(),則HashMap將“看到”我的兩個對象的hashCode是不同的,並且得出結論,不需要調用equals( )。 如果是這樣,則HashMap正在執行合同的至少一部分。 並且,這可能是HashMap優化的另一個體現。

但是,您(greenSocksRock)寫道:“ ...密鑰的hashCode()實現沒有為不同的密鑰返回足夠不同的哈希值。”請您詳細說明一下嗎?

謝謝。

PS對不起,我仍在嘗試着解決StackOverflow編輯器的問題。

編譯器和JVM都不強制執行hashCode / equals合同。 合同在Object您的班級之間,即您有責任遵守並執行該合同!

在Java中, Object類列出了.equals().hashCode() ,這是大多數基於散列的標准庫類所依賴的.hashCode() 現在,如果您實現自己的類,則它將隱式擴展Object ,因此,如果您希望您的類與依賴該合同的其他類一起正常工作,則應該在自己的實現中強制執行常規協定。

提醒一下,來自Object文檔

如果根據equals(Object)方法,兩個對象相等,則在兩個對象中的每個對象上調用hashCode方法必須產生相同的整數結果。

在沒有看到您的實現的情況下,我只能猜測為什么將對象放入Map時會調用equals() ,而我的猜測是您鍵的hashCode()實現沒有為不同的對象返回足夠不同的哈希值鍵。
例如,當您將某些東西放入HashMap ,它將調用該鍵的hashCode()方法,以找到存儲您的值的位置。 如果該位置已經包含一個值,則可能會調用鍵的equals()方法以弄清楚下一步該怎么做。

當您說要“防止在地圖上添加對象”時,我不確定我是否理解上一個問題中您要做什么。 這是你肯定能夠使用自定義做equals實現,如果你想。 在將新條目放入地圖之前,請根據您的情況查看Map.containsKey()Map.containsValue()

最后,建議閱讀Joshua Bloch的“ Effective Java,第二版”中的項目8和9 如果可以的話,以獲得更深入的解釋。

AFAIK編譯器不強制執行它。 閱讀此書可以更好地理解主題http://tutorials.jenkov.com/java-collections/hashcode-equals.html

哈希圖在內部實現為鏈接列表的集合。 搜索對象(帶有傳遞的鍵)的通常機制是首先對鍵進行哈希處理,然后遍歷鏈接列表中與哈希值對應的各個對象。

按照相同的邏輯,對於HashMap中的對象,僅當hashCode()方法為兩個對象返回相同的哈希值時,才調用equals()方法。

因此,始終建議在實現自定義類時不僅覆蓋equals()方法,而且還覆蓋hashCode()方法。

暫無
暫無

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

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