2014-03-27 29 views
1

我想創建一個搜索算法,它將座標對存儲在名爲HashSquareSpec的包裝類中。爲了避免重複,並保持插入順序,我將每個HashSquareSpec插入LinkedHashSet。儘管我已經重寫了equals()方法和hashCode()方法,但LinkedHashSet仍然接受兩個HashSquareSpec對象,其中有相同的座標對,其中包含 。LinkedHashSet不刪除重複

public static void main(String [] args) 
{ 
    LinkedHashSet<HashSquareSpec> firedShots = new HashLinkedSet<HashSquareSpec>(); 
    HashSquareSpec a = new HashSquareSpec(1,2); 
    HashSquareSpec b = new HashSquareSpec(2,2); 
    HashSquareSpec c = new HashSquareSpec(1,2); 
    HashSquareSpec d = new HashSquareSpec(3,2); 

    firedShots.add(a); 
    firedShots.add(b); 
    firedShots.add(c); 
    firedShots.add(d); 
    System.out.println(a.equals((SquareSpec)c)); 
    Iterator l = firedShots.iterator(); 
    while(l.hasNext()) 
    { 
     System.out.println(l.next().hashCode()); 
    } 
} 

Output: 
true 
38444474 
38474265 
38444474 
38504056 

HashSquare類

public class HashSquareSpec extends SquareSpec 
{ 
    public HashSquareSpec(int sx, int sy) 
    { 
    super(sx,sy); 
    } 

    public HashSquareSpec(String codeString) 
    { 
    super(codeString); 
    } 

    @Override 
    public int hashCode() 
    { 
    return this.toString().hashCode(); 
    } 

    public boolean equals(HashSquareSpec other) 
    { 
    if(this.toString().equals(other.toString())) 
     return true; 
    else 
     return false; 
    } 
} 

和超級類HashSquareSpec

public class SquareSpec { 
    public int x; 
    public int y; 

    public SquareSpec(int sx, int sy) { 
     this.x = sx; 
     this.y = sy; 
    } 

    public SquareSpec(String codeString) { 
     this.x = Integer.parseInt(codeString.substring(1,2)); 
     this.y = Integer.parseInt(codeString.substring(3,4)); 
    } 

    public String toString() { 
     return("(" + x + "," + y + ")"); 
    } 

    public boolean equals(SquareSpec other) { 
     return (other.x == this.x && 
       other.y == this.y); 
    } 
    } 

的儘管有許多不同的hashCode變化和Eclipse等於和hashCode一代, firedShots數據結構保持接受重複。我的代碼有什麼問題?

回答

3

你是在正確的軌道上,覆蓋hashcodeequals,除非你被錯誤地覆蓋在HashSquareSpec(和SquareSpec)的equals method from Object。該參數必須是Object。因爲它沒有被覆蓋,因此調用Objectequals,它比較對象引用以查看它們是否是同一個對象。他們不是,所以「重複」是允許的。

嘗試:

@Override 
public boolean equals(Object other) 
{ 
    if(this.toString().equals(other.toString())) 
    return true; 
    else 
    return false; 
} 

你也應該測試是否othernull然後確保other是同一類型。

包含@Override註釋,以便如果該方法實際上不覆蓋任何內容,則編譯器會發出抱怨。

+0

這不是一個很好的'equals'實現;你應該做'instanceof'檢查。 (例如,你的實現不是對稱的,因爲這將等於一個String。) –

+1

@LouisWasserman非常真實,這就是爲什麼包括一個關於空值檢查的句子,並檢查'​​other'是否是相同類型的。 – rgettman

0

它仍然接受,因爲您不覆蓋equals方法。您需要覆蓋boolean equals(Object)。問題是你正在定義一個新方法,如boolean equals(SquareSpec)

這裏是LinkedHashSet#add(T)最終調用方法:

HashMap#put(K, V)

@Override public V put(K key, V value) { 
    if (key == null) { 
     return putValueForNullKey(value); 
    } 

    int hash = secondaryHash(key.hashCode()); 
    HashMapEntry<K, V>[] tab = table; 
    int index = hash & (tab.length - 1); 
    for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) { 
     if (e.hash == hash && key.equals(e.key)) { 
      preModify(e); 
      V oldValue = e.value; 
      e.value = value; 
      return oldValue; 
     } 
    } 

正如你所看到的,它比較了使用hashCodeequals(Object)