2011-08-02 67 views
0

我需要實現equals()方法可以放在它的HashSet的一個項目的Maker.The項目可以有字段如下平等項目的

class Item{ 
    private String isbn; 
    private String name; 
    private double price; 
... 
} 

class Maker{ 
    private String name; 
    private Set<Item> items; 
    public Maker() { 
     super(); 
     items = new HashSet<Item>(); 
    } 
... 
} 

如果我實現由等於比較這三個字段,寫基於這些字段的hashCode(),我會得到錯誤的結果時

1.add item to hashset 
2.modify the price of item 
3.try to find if item exists in hashset 


@Override 
public boolean equals(Object o){ 
    if(o == this){ 
     return true; 
    } 
    if (!(o instanceof Item)){ 
     return false; 
    } 
    Item a = (Item)o; 
    if(hasSameName(a) && hasSameIsbn(a) && hasSamePrice(a)){ 
     return true; 
    } 
    else{ 
     return false; 
    } 
} 

@Override 
public int hashCode(){ 
    int hash = 41 + this.isbn.hashCode(); 
    hash = hash*41+ new Double(this.price).hashCode(); 
    hash = hash*41 + this.name.hashCode(); 
    return hash; 
} 

... 
Set<Item> items = new HashSet<Item>(); 
Item item1 = new Item(); 
item1.setName("crystal bird"); 
item1.setIsbn("1111"); 
item1.setPrice(120.5); 

items.add(item1); 

System.out.println(items.contains(item1));//returns true 
item1.setPrice(177.0); 
System.out.println(items.contains(item1));//returns false 

什麼是克服這種解決辦法嗎?我應該做的hashCode()只依賴於ISBN並且假設它在物品的使用期限內不會改變。

任何幫助讚賞

mark。

回答

1

HashSet.add()方法(這基本上HashMap.put()方法)發現在自保持內部表的最佳位置根據hashcode()

如果您更改該項目的值即KeyHashMap因此它會改變hashcode()值導致異常結果。

您應該只考慮ISBN作爲對象的關鍵,以儘可能簡化事情。

@Override 
public boolean equals(Object o){ 
    if(o == null){ 
     return false; 
    } 
    if(o == this){ 
     return true; 
    } 
    if (!(o instanceof Item)){ 
     return false; 
    } 
    Item a = (Item)o; 
    if(hasSameIsbn(a)){ 
     return true; 
    } 
    else{ 
     return false; 
    } 
} 

@Override 
public int hashCode(){ 
    return (41 + this.isbn.hashCode()); 
} 
5

是,ISBN是一個典型的自然標識 - 僅使用它的兩個equals(..)hashCode()

0

是的,因爲你的價格計算的hashCode的一部分,並且在燕鷗計算爲你的對象的平等,爲您設置了不同的價格它的哈希碼的變化,因此你不能找到相同的項目。 ()方法使用equals()來檢查一個集合是否包含同一個對象,並且因爲你的價格是一個平等檢查因素,所以在你修改它之後就不再是平等的了,因此contains()找不到它。

1

在您可能錯過的API某處有一條黃金法則:
當對象位於HashMap/Set中時,不得更改hashCode!

HashMap/Set使用hashCode以更快的方式排列和查找對象。所以你需要提供一個不會改變的hashCode。在任何情況下,hashCode都不需要是唯一的,但如果是的話,它將提供更好的訪問時間。

該解決方案已被其他人建議:使用ISBN作爲hashCode。我提供了一個非常好的獨特性,不會改變!