2014-03-31 74 views
2

簡單的問題。我有一個對象:用已經唯一的整數生成哈希碼

class User { 

    int id; 
    String username; 

    public User() { 
    } 

    public User(int id, String username) { 
     this.id = id; 
     this.username = username; 
    } 

    @Override 
    public String toString() { 
     return id + " - " + username; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 7; 
     hash = 31 * hash + this.id; 
     return hash; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final User other = (User) obj; 
     return this.id == other.id; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getUsername() { 
     return username; 
    } 

    public int getId() { 
     return id; 
    } 
} 

基於int id確定了它們的平等(這是一個數據庫ID)。

的Netbeans自動生成該hashCode()方法:

@Override 
public int hashCode() { 
    int hash = 7; 
    hash = 31 * hash + this.id; 
    return hash; 
} 

的問題是:是否有任何優勢,這在剛剛返回(已經)獨特int id

@Override 
public int hashCode() { 
    return id; 
} 

碰撞是不可能的。

,對嗎?

+1

hashCode的目標()不以避免碰撞。 –

+0

從某種角度來看,它取決於你如何實現equals。如果你想添加一個數據值的克隆呢? – Rogue

+0

[Joshua Block:Effective Java](http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf),Item 9 –

回答

1

1)你可以這樣做:

@Override 
public int hashCode() { 
    return 1; // or any int constant here 
} 

2) 如果說在
數據庫百萬這樣的對象,你也許可以這樣做:

@Override 
public int hashCode() { 
    return id % 10000; 
} 

這樣你1,000,000個物體將會有10000個桶。

3)您可以調節idInteger,只是這樣做:

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

或這相當於做:

@Override 
public int hashCode() { 
    return id; 
} 

1)和3)邊界情況的一個hashCode實現。方法2)在中間的某個地方。

+1

這很混亂 - 爲什麼你會自願增加(i)中的碰撞風險或使用Integer的散列碼,它在(ii)中返回int值本身? – assylias

+0

@assylias只是想證明兩者在OP的情況下都是有效的散列函數。這是兩種邊界情況。其實真正的邊界情況不是'return id%10000;'''return 1;'。 –

+0

答覆已更新。 –

1

Object.hashCode() javadoc告訴你一切你需要知道回答你的問題。

hashCode的一般合同是:

  • 每當它是一個Java應用程序的執行期間,在同一對象不止一次上調用,hashCode方法必須一致地返回相同的整數,條件沒有在對象的等值比較中使用的信息被修改。該整數不需要從應用程序的一次執行到同一應用程序的另一次執行保持一致。

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

  • 根據equals(java.lang.Object)方法,如果兩個對象不相等,則不要求對這兩個對象中的每一個調用hashCode方法都必須產生不同的整數結果。但是,程序員應該意識到,爲不相等的對象生成不同的整數結果可能會提高散列表的性能。

0

有之間id31 * 7 + id所以返回id代替一個雙射是等價的。因此,我會簡單地return id;並刪除不必要的計算/併發症。

但會構成一個兼容的散列碼方法?讓我們回到的javadoc:

hashCode的一般合同是:

  • 每當它是一個Java應用程序的執行期間,在同一對象不止一次調用,hashCode方法必須始終返回相同的整數,前提是沒有用於修改對象的等號比較的信息。該整數不需要從應用程序的一次執行到同一應用程序的另一次執行保持一致。
  • 如果兩個對象根據equals(Object)方法相等,則對這兩個對象中的每個對象調用hashCode方法必須產生相同的整數結果。
  • 根據equals(java.lang.Object)方法,如果兩個對象不相等,則不要求對兩個對象中的每個對象調用hashCode方法必須產生不同的整數結果。但是,程序員應該意識到,爲不相等的對象生成不同的整數結果可能會提高散列表的性能。

它是否適用於您的情況?

  • (i)有希望滿足:你不會在給定的對象上任意改變id,對吧?
  • (二)如果兩個用戶都是平等的,他們具有相同的散列碼:是的,因爲你的平等是基於ID太
  • (III)成立