2017-04-10 106 views
0
class UserScoring implements Comparable<UserScoring> { 

     User user; 
     int score; 

     UserScoring(User user, int score) { 
      this.user = user; 
      this.score = score; 
     } 

     @Override 
     public int compareTo(UserScoring o) { 
      if (this.score < o.score) { 
       return 1; 
      } 
      else if (this.score == o.score) { 
       return 0; 
      } 
      return -1; 
     } 

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

     public boolean equals(Object obj) { 
      if (obj == null) { 
       return false; 
      } 
      if (getClass() != obj.getClass()) { 
       return false; 
      } 
      final UserScoring other = (UserScoring) obj; 

      return user.equals(other.user); 
     } 
    } 

我想創建一個類UserScoring可它的可變分數的基礎上進行排序,其獨特性是由其用戶決定返回變量的哈希碼。重寫hashCode方法在類

這意味着:

  1. 如果我有點UserScoring對象的使用Collections.sort()的集合,我想基於從高到低的順序分數進行排序。我已經爲同樣的方法重寫了compareTo方法。
  2. 如果我創建一組UserScoring對象,則不需要同一用戶的兩個UserScoring對象。我已經覆蓋了相同的equals和hashcode方法。

我在這裏有兩個疑問: 1.返回UserScoring對象的散列碼與User對象相同是否是錯誤的。這對我來說肯定是錯誤的。但是它可能導致什麼問題呢?

  1. 有什麼辦法可以確保只有高分的UserScoring對象保存在集合中(並且分數較小的對象被驅逐或未添加)每當試圖添加同一用戶的兩個UserScoring對象時。

    UserScoring us1 = new UserScoring(u1, 1000); 
    UserScoring us2 = new UserScoring(u1, 100); 
    Set<UserScoring> set = new HashSet<>(); 
    set.add(us1); 
    set.add(us2); 
    

這套如何可以包含US1代替US2?

+2

的hashCode和equals的實現必須相互匹配。你的不。 –

+1

@OliverCharlesworth從何而來,他們必須匹配?我能在這裏做什麼,所以他們匹配? – tanvi

+0

@OliverCharlesworth我明白這個實現是錯誤的,因爲對於兩個不同分數的UserScoring對象,這意味着它們是平等的,它不應該。但是我想把這些對象放在一個集合中,以便一個用戶只有一個對象。有沒有辦法做到這一點? – tanvi

回答

1
  1. 返回UserScoring對象的散列碼與User對象相同是否是錯誤的。這對我來說肯定是錯誤的。但是它可能導致什麼問題呢?

這沒有錯。在這種情況下,我們說UserScoring對象的「標識」是關聯的User對象。但是,這要求您的equals()方法也必須遵守此身份約定,因此它必須實現爲return Objects.equal(this.user, other.user)

  • 有什麼辦法都確保了較高的分數的UserScoring對象保持在設定每當有一個嘗試添加兩個相同UserScoring對象用戶。
  • 我不認爲有任何的方式與未修改HashSet的自動化,但你可以提供自己的Set裝飾(稱呼它,比如,RankingSet)的檢查對象被添加侵害的對象已經在底層Set並保持較高的排名。 (在你的情況下排名是分數。)你可以在Interwebz中查看一個CollectionDecorator,你可以使用它來減少你需要做的工作量:它將使你只能覆蓋add()方法,讓其餘的的方法來委託給底層設置

    ,因爲你需要能夠比較您的UserScoring對象,另外一個問題你可能碰到的是你的equals()方法不與Comparable.compareTo()返回的結果一致。解決這個問題的一種方法是通過而不是使得UserScoring具有可比性,而是實現了一個單獨的Comparator,它根據他們的得分比較UserScoring對象。

    (因此,RankingSet將需要接受這樣的Comparator作爲構造函數的參數。)

    +0

    非常感謝邁克。這有助於。我想改寫我的問題2「是否有任何方法可以確保將更高分的UserScoring對象保留在集合中,並且每當嘗試添加兩個UserScoring對象時,都會刪除更少的分數同一個用戶「。我不想用同一個用戶保留兩個對象。 – tanvi

    +1

    我明白了。我不認爲有任何方法可以通過一個未修改的HashSet實現自動化,但是你可以提供你自己的'RankingSet'裝飾器,它檢查被添加的對象是否已經在底層'Set'中的對象上,並且保留了更高級別的對象。 (等級由提供的「比較器」確定)。您可以在Interwebz中查看「CollectionDecorator」,您可以使用它來減少您需要執行的工作量:它將使您只能覆蓋「添加()'方法,並讓其餘的方法委託給底層的'Set'。 –

    +0

    我聽說過裝飾模式,但沒有使用它。謝謝@Mike。我會看看這個。 – tanvi