2012-08-26 35 views
17

Object在Java中有hashCode方法,但是,它僅用於關聯容器,如HashSetHashMap。爲什麼它是這樣設計的? Hashable接口有hashCode方法看起來更加優雅的解決方案。爲什麼在Java中沒有Hashable接口

+0

爲什麼你需要特殊的接口,當你可以覆蓋它的每一個地方,Object是默認的超類? – kosa

+2

@Namban問題更多的是「爲什麼每個對象都有一個hashCode()方法,當它只被少數java.util。*集合類使用時」。即爲什麼不存在例如一個ObjectHash接口,就像有一個Comparable接口一樣,等等。 – nos

+1

這是一個討論主題而不是問題,所以它不適合SO。 – Keppil

回答

6

我認爲主要的觀點認爲,有一個明確定義的默認值hashCode可以計算任何Java對象以及同樣明確定義的equals。從所有對象中扣除此功能根本沒有理由,當然,有很多原因而不是來扣留它。所以在我的書中這是一件不容易的事。

+0

我不認爲他在說應該有一個獲得'hashCode'的通用程序;他指出'has​​hCode'應該成爲某個接口的一部分'Hashable',而不是留在'Object'中。 – oldrinb

+0

@veer是的,正是 – karlicoss

+0

@veer好的,現在我明白了。我誤讀了。但是,這仍然是一個稍微不同的原因。 –

0

這個問題與另一個問題是重複的,它詢問爲什麼沒有像Comparator(與Comparable不同)但是用於哈希的接口。 .NET包含這樣一個接口,稱爲IEqualityComparer,它看起來也可以像Java一樣。事實上,如果有人想要例如有一個Java集合,例如以不區分大小寫的方式將字符串映射到其他對象(可能是IEqualityComparer的最常見用法),必須將字符串包裝在對象中,而對象的方法不區分大小寫。

我懷疑大問題是,雖然「equalityComparer」接口可能很方便,但在許多情況下,高效地測試等價關係需要緩存信息。例如,儘管不區分大小寫的字符串散列函數可以使傳入的字符串只有大寫字母的副本並對其調用hashCode,但要避免每次請求特定字符串的散列碼都要重複轉換大寫和大寫值的散列。相比之下,「不區分大小寫的字符串」對象可以包含字符串的大寫字母副本的字段,然後只需爲該實例生成一次即可。

EqualityComparer能夠實現合理的性能,如果它包含的東西像一個WeakHashMap<string,string>轉換原始字符串爲大寫,只有字符串,但這樣的設計要麼需要不同的線程儘管缺乏外部可見的狀態來使用不同的EqualityComparer的情況下,或否則,即使在單線程場景中,也需要性能搶奪鎖定和同步代碼。

順便說一句,比較器式接口產生的第二個問題是使用外部提供的比較器(不管它是比較排名還是相等)的集合類型是比較器本身成爲類的狀態的一部分它使用它。如果散列表使用不同的EqualityComparer實例,則可能無法知道它們可以安全地視爲等同,即使兩個比較器在所有情況下的行爲都是相同的。

0

有什麼好處,它有一個接口,每個對象實現無論如何通過繼承?由於Object實現它並且應該是可散列的,因此它的聲明中必須有implements Hashable,並且所有其他類將繼承它,因爲它們是Object的子類。有一個接口Hashable只是說明顯而易見的。

+0

根據同樣的想法,我們可以問,有什麼好處,有兩種方法,每個對象都有,但從來沒有使用過?而當他們最終只使用一種方法而不是使用調用者代碼的方式使用時就會失敗。那麼這個設計決定有什麼合理性? –