[英]Java hashCode, artificial fields?
想象以下問題:
// Class PhoneNumber implements hashCode() and equals()
PhoneNumber obj = new PhoneNumber("mgm", "089/358680");
System.out.println("Hashcode: " +
obj.hashCode()); //prints "1476725853"
// Add PhoneNumber object to HashSet
Set<PhoneNumber> set = new HashSet();
set.add(obj);
// Modify object after it has been inserted
obj.setNumber("089/358680-0");
// Modification causes a different hash value
System.out.println("New hashcode: " +
obj.hashCode()); //prints "7130851"
// ... Later or in another class, code such as the following
// is operating on the Set:
// Unexpected Result!
// Output: obj is set member: FALSE
System.out.println("obj is set member: " +
set.contains(obj));
如果我有一個類,並且希望所有字段都可編輯並且仍然可以使用set / hashCode。 在創建對象時設置的類中創建人為的不可編輯字段是一個好主意嗎? 例如,當前時間(以毫秒為單位)。 有了該字段后,我就可以基於該哈希碼,並且仍然可以編輯所有“真實”字段。 這是個好主意嗎?
我堅信您提出的用例很差:如果您需要修改Set
對象,則一定要刪除舊對象,然后重新添加新對象(或使用另一個java.util.Collection
)。 以您的示例為例:
Set<PhoneNumber> set = new HashSet();
set.add(obj);
// Modify object after it has been inserted
set.remove(obj);
obj.setNumber("089/358680-0");
set.add(obj);
hashCode
的全部目的是創建一個類似對象的存儲桶以減少搜索空間,因此它應該是不變的,但對您有用(如果您使用人工字段,以后如何在集合中找到對象?如何做)如果您沒有任何類型的持久性存儲,則可以檢索此人工字段-數據庫中的ID是人工字段IMHO的例外)。
解釋的意思
hashCode
的全部目的是創建一個類似對象的存儲桶以減少搜索空間
看看以下示例代碼: http : //ideone.com/MJ2MQT 。 我(錯誤地)使用相同的哈希碼創建了對象,然后將它們都添加到集合中; 正如預期的那樣,該集合包含這兩個元素,因為哈希碼用於檢索發生沖突的元素,然后調用equals
方法來解決此沖突。 沖突(讀取different objects which return same hash code
)是不可避免的,而正確設計哈希碼功能的目標是盡可能減少沖突。
出於您在代碼中說明的原因,將可變對象存儲在哈希集中或將它們用作哈希映射中的鍵絕對不是一個好主意。
另一方面,定義一個用作對象ID
的人為數將使哈希碼最初的目的無效,因為它無助於通過限制搜索來找到與給定對象相等的對象具有相同哈希碼的對象。
實際上,您的解決方案與從“人工哈希碼”到可變的PhoneNumber
對象構造Map<Integer,PhoneNumber>
並無不同。 如果您需要通過關聯查找對象,那么從人工ID到可變對象的HashMap
是可行的方法。
通常,對數據對象使用唯一的標識符是有意義的,尤其是當您將它們持久保存在某個數據庫中時。 它將使您能夠輕松實現equals
和hashCode
,這僅取決於此單個標識符。
我不確定以毫秒為單位的當前時間。 將是最好的選擇,但您絕對應該生成一些唯一的ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.