2016-12-16 7 views
0

ich eine Klasse Skill wie genannt haben:Suche nach einem Objekt der Basisklasse in einem Set von abgeleiteten Klasse

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; 
    } 
} 

Eine andere genannt PSkill wie:

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; 
    } 
} 

Meine Forderung: Suche ein Set von PSkill Objekte, um eine Übereinstimmung für Skill Objekt zu finden. Zum Beispiel: Skill - type:1, level:2 ist eine Übereinstimmung für PSkill - type:1, level:2, preferenceLevel: any, mandatory: any

Wenn ich das unten laufe, funktioniert es.

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 
    } 
} 

Und ich weiß, warum, weil die hashCode() Implementierung für beide Typen gleich ist und in HashSet Implementierung wird key.equals(k) verwendet und Schlüssel in meinem Fall ist Skill Objekt und damit die Gleichheit funktioniert.

Von HashSet Implementierung

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; 
} 

Ich weiß, ich brach die hashCode() und equals() Vertrag. Aber der Code funktioniert wie er sollte, d. H. Prüfen, ob ein Skill mit irgendeinem der PSkill s in dem Satz übereinstimmt.

Meine Frage ist: Ist die Gleichheitsprüfung key.equals(k) in HashSet Umsetzung abhängig und könnte in einer zukünftigen Version umgekehrt werden, das heißt k.equals(key) und der Code wird aufhören zu arbeiten? Gibt es auch bessere Möglichkeiten, dies zu tun, die es weniger fragil machen könnten, ohne einfach die Sammlung zu überfliegen? Danke

+0

funktioniert es immer noch, wenn Sie die Reihenfolge der Einfügungen ändern? – AdamSkywalker

+0

@AdamSkywalker Ändern Reihenfolge der Einfügungen von 'PSkill' Objekte in das Set? Nun ja. – GurV

Antwort

0

Dieses Verhalten ist sicherlich nicht garantiert. Der Vertrag besagt, dass Sie, wenn Sie korrekte Implementierungen von hashCode und equals bereitstellen, eine korrekte Implementierung eines hashsets erhalten. Wenn Sie Ihrem Vertragsende nicht folgen, haben Sie keine Garantie, wie gut ein Satz funktioniert.

Verwandte Themen