210 likes | 450 Views
Equals, Hashcode und C ompareTo. Micha Kessler mkessler@next-level-integration.com www.next-level-integration.com. Inhalt. Equals Hashcode CompareTo. Equals. Gibt an, ob zwei Objekte gleich sind Wir bei Collections benutzt Nicht sinnvoll zu überschreiben wenn: Logisches equals egal
E N D
Equals, Hashcode und CompareTo Micha Kessler mkessler@next-level-integration.com www.next-level-integration.com
Inhalt • Equals • Hashcode • CompareTo
Equals • Gibt an, ob zwei Objekte gleich sind • Wir bei Collections benutzt • Nicht sinnvoll zu überschreiben wenn: • Logisches equals egal • Jedes Element unterschiedlich • Equals der Superklasse reicht • Wird definitiv nicht benutzt
Equals • Reflexiv • x.equals(x) == true //x != null • Symmetrisch • x.equals(y) == y.equals(x) • Problematisch bei Ober- und Unterklasse • Transitiv • x.equals(y) && x.equals(z) y.equals(z) • Problematisch bei Ober- und Unterklasse • Konsistent • x.equals(y) jederzeit das gleiche Ergebnis • Problematisch bei veränderlichen Objekten • x.equals(null) == false
Equals Beispiel public class Point{ private final int x; private final int y; public Point(int x, int y){ this.x=x; this.y=y; } @Override public boolean equals (Object o){ if(!(o instanceof Point)) return false; Point p = (Point) o; return p.x == x && p.y == y; } }
Equals Beispiel public class ColorPoint extends Point{ private final Color color; public ColorPoint(int x, int y, Color color){ super(x,y); this.color = color; } @Override public boolean equals (Object o){ if(!(o instanceof ColorPoint)) return false; return super.equals(o) && ((ColorPoint) o).color == color; } }
Equals Beispiel Symmetrie gebrochen: Point p = new Point(1,4); ColorPoint cp = new ColorPoint(1,4,Color.RED); p.equals(cp) != cp.equals(p);
Equals Beispiel @Override public boolean equals (Object o){ if(!(o instanceofPoint)) return false; if(!(o instanceof ColorPoint)) return o.equals(this); return super.equals(o) && ((ColorPoint) o).color == color; }
Equals Beispiel Transitivität verletzt: Point p = new Point(1,4); ColorPoint cp1 = new ColorPoint(1,4, Color.RED); ColorPoint cp2 = new ColorPoint(1,4, Color.BLUE); cp1.equals(p) -> true cp2.equals(p) -> true Aber: cp1.equals(cp2) -> false
Equals Beispiel @Override public boolean equals (Object o){ if(o == null || o.getClass() != getClass()) return false; Point p = (Point) o; return p.x == x && p.y == y; }
Equals Beispiel Liskovsches Substitutionsprinzip: Eigenschaften, die anhand der Spezifikation des vermeintlichen Typs eines Objektes bewiesen werden können, sollten auch dann gelten, wenn das Objekt einem Untertyp dieses Typs angehört. Gemischter Aufruf false
Equals Beispiel @Override public boolean equals (Object o){ if(!(o instanceof Point)) return false; Point p = (Point) o; return p.canEquals(this) && p.x == x && p.y == y; } protected boolean canEquals(Object o){ return o instanceof Point; }
Equals Beispiel @Override public boolean equals (Object o){ if(!(o instanceof ColorPoint)) return false; ColorPoint cp = (ColorPoint) o; return cp.canEquals(this) && super.equals(cp) && cp.color == color; } @Override protected boolean canEquals(Object o){ return o instanceof ColorPoint; }
Hashcode • Liefert einen Integer-Wert • Gleiche Objekte liefern immer den gleichen Wert • Unterschiedliche Objekte können den gleichen Wert liefern
Hashcode • Wenn equals überschrieben wird hashCode überschreiben • Wichtig für HashTable, HashMap und HashSet • zwei gleiche Elemente (x.equals(y) == true) können unterschiedliche Hashwerte haben werden nicht gefunden • Alle Elemente, die bei equals eine Rolle spielen, verwenden • Gute Verteilung
Hashcode Schema Felder umrechnen • boolean: (f ? 1: 0) • byte, char, short, int: (int) f • long: (int) (f^(f>>>32)) • float: Float.floatToIntBits(f) • double: Double.doubleToLongBits(f) wie long • Object: rekursiv f.hashcode() • null 0
Hashcode Schema @Override public int hashcode(){ int result=5; result = 31 * result + zahl1; result = 31 * result + zahl2; result = 31 * result + feld1.hashcode(); return result; }
Hashcode Schema(Cache) private volatile int hashCode; @Override public int hashcode(){ int result = hashCode; If(result == 0){ result = 5; result = 31 * result + zahl1; result = 31 * result + zahl2; result = 31 * result + feld1.hashcode(); hashCode = result; } return hashCode; }
CompareTo public interface Comparable<T>{ int compareTo(T t); } • Rückgabewert positiv, null oder negativ, wenn das Element kleiner, genau so groß oder größer ist als das this Objekt • ClassCastException wenn der Typ nicht stimmt • NullPointerException wenn null übergeben wird • Schafft eine „Natürliche Ordnung“ • Wichtig für interne Aufrufe bei Sortieralgorithmen und Baumstrukturen (z.B. TreeSet, Collections.sort, Array.sort, PriorityQueue, PriorityBlockingQueue, EnumSet)
CompareTo • Reflexiv • x.compareTo(x) == 0 • Symmetrisch • sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) • Gilt auch für Exceptions • Transitiv • sgn(x.compareTo(y)) > 0 && sgn(y.compareTo(z)) > 0 sgn(x.compareTo(z)) > 0 • x.compareTo(y) == 0 sgn(y.compareTo(z)) == sgn(x.compareTo(z)) • Sollte auch Konsistent zu equals sein • (x.compareTo(y) == 0) == (x.equals(y))
Kontakt Micha Kessler mkessler@next-level-integration.com