2016-12-16 19 views
0

の設定で基本クラスのオブジェクトを検索し、私のようにSkillというクラスました:私の要件派生クラス

public class PSkill extends Skill { 
    private final int preferenceLevel; 
    private final boolean mandatory; 

    public PSkill(int type, int level, int preferenceLevel, boolean mandatory) { 
     super(type, level); 
     this.preferenceLevel = preferenceLevel; 
     this.mandatory = mandatory; 
    } 

    // Getters 

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

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj instanceof PSkill) { 
      PSkill that = (PSkill) obj; 
      return super.equals(obj) 
       && this.preferenceLevel == that.preferenceLevel 
       && this.mandatory == that.mandatory; 
     } 
     return false; 
    } 
} 

検索A

public class Skill { 
    private final int type; 
    private final int level; 

    public Skill(int type, int level) { 
     this.type = type; 
     this.level = level; 
    } 

    // Getters 

    @Override 
    public int hashCode() { 
     int h = 17; 
     h = 31 * h + type; 
     h = 31 * h + level; 
     return h; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj instanceof Skill) { 
      Skill that = (Skill) obj; 
      return this.type == that.type && this.level == that.level; 
     } 
     return false; 
    } 
} 

別としてPSkillと呼ばれますSkillオブジェクトの一致を見つけるためにPSkillオブジェクトのセット。 例:Skill - type:1, level:2PSkill - type:1, level:2, preferenceLevel: any, mandatory: anyと一致します

以下を実行すると動作します。

public class Invoker { 
    public static void main(String[] args) { 
     Set<PSkill> skills = new HashSet<>(Arrays.asList(new PSkill(1, 1, 1, true), new PSkill(1, 2, 1, true))); 
     System.out.println(skills.contains(new Skill(1, 1))); // prints true 
     System.out.println(skills.contains(new Skill(1, 3))); // prints false 
    } 
} 

そして、両方のタイプのhashCode()実装が同じであるとHashSet実装では、key.equals(k)が使用され、私の場合は、キーがSkillオブジェクトであり、したがって、平等が働くので、私は理由を知っています。

HashSetの実装から

final Node<K,V> getNode(int hash, Object key) { 
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k; 
    if ((tab = table) != null && (n = tab.length) > 0 && 
     (first = tab[(n - 1) & hash]) != null) { 
     if (first.hash == hash && // always check first node 
      ((k = first.key) == key || (key != null && key.equals(k)))) // here 
      return first; 
     if ((e = first.next) != null) { 
      if (first instanceof TreeNode) 
       return ((TreeNode<K,V>)first).getTreeNode(hash, key); 
      do { 
       if (e.hash == hash && 
        ((k = e.key) == key || (key != null && key.equals(k)))) // and here 
        return e; 
      } while ((e = e.next) != null); 
     } 
    } 
    return null; 
} 

私はhashCode()equals()契約を破った知っています。しかし、コードは、つまり、Skillがセット内のPSkillと一致するかどうかを確認する必要があります。

私の質問は:HashSet実装に依存平等チェックkey.equals(k)ですし、すなわちk.equals(key)将来のリリースで逆転させることができ、コードは動作を停止しますか? また、それを行うより良い方法は、単純にコレクションをループすることなく、壊れにくくすることができますか?ありがとう

+0

挿入順を変更しても機能しますか? – AdamSkywalker

+0

@AdamSkywalkerは 'PSkill'オブジェクトのセットへの挿入順序を変更しますか?はい、そうです。 – GurV

答えて

0

この動作は確かに保証されません。契約では、hashCodeとequalsの正しい実装を提供すると、ハッシュセットの正しい実装が得られるということです。あなたが契約の終わりに従わなければ、あなたはセットがうまくいくかどうかについての保証はありません。