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
funktioniert es immer noch, wenn Sie die Reihenfolge der Einfügungen ändern? – AdamSkywalker
@AdamSkywalker Ändern Reihenfolge der Einfügungen von 'PSkill' Objekte in das Set? Nun ja. – GurV