equals Methode möglichst effizient

ocsme

Top Contributor
Guten Tag zusammen,

ich befasse mich derzeit etwas mit dem Collection-Framework von Java. Dabei wird ja nur mit Referenztypen gearbeitet und um diese zu vergleichen benötigt man ja die von Object ererbte Methode equals :)

Nun wollte ich mal nachfragen ob es eine effizienten Weg gibt diese equals Methode zu schreiben. Wir haben früher immer sämtliche Primitivien Typen mittels "==" auf Gleichheit überprüft und für Referenztypen dann eine equals Methode. Doch je mehr Referenztypen in einer Klasse stehen desto größer muss eine solche equals Methode werden.

Unser Prof meinte wir sollen uns eine eigene hashCode() Methode schreiben die einen eindeutigen Wert für jedes Objekt zurück gibt und man so dann eben auf Gleichheit Prüfen kann :) alles schön und gut doch ich hab keine Idee wie ich mir so eine hashCode() Methode schreiben soll :p
Hab mir zu diesem Thema auch schon einiges angeschaut und auch sowas haben wir in ALDA bearbeitet doch was wäre wenn für ein verschiedenes Objekt dann der selbe Hash raus kommt?

Hat jemand eine Idee? oder sprengt das Thema den rahmen ?

LG
 

Robat

Top Contributor
doch was wäre wenn für ein verschiedenes Objekt dann der selbe Hash raus kommt?
Dann ist dein Hashcode Methode einfach nicht sauber implementiert. Der "Vertrag" zwischen equals(Object) und hashcode() besagt, dass wenn 2 Objekte durch die equals(Object) Methode als gleich identifiziert werden, muss die hashcode() Methode den selben Integerwert zurückliefern.
Das ist an sich auch nicht so schwer. Seit Java 7 (glaub ich) gibt es die Objects#hash(Object...) Methode, die für dich die Arbeit macht.
Java:
@Override
public int hashCode() {
    return Objects.hash(attr1, attr2, ... , attrN);
}
 

mihe7

Top Contributor
Unser Prof meinte wir sollen uns eine eigene hashCode() Methode schreiben die einen eindeutigen Wert für jedes Objekt zurück gibt und man so dann eben auf Gleichheit Prüfen kann
Man kann im Allgemeinen mit dem Hash-Code nur die Ungleichheit feststellen, nicht jedoch die Gleichheit, d. h. aus a.equals(b) folgt a.hashCode() == b.hashCode(), die Umkehrung gilt jedoch nicht. Das einzige, was man mit Sicherheit sagen kann (können muss): a.hashCode() != b.hashCode() ==> !a.equals(b)

Dazu musst Du Dir lediglich Strings ansehen: der Hash-Code ist eine 32-Bit-Zahl, hat also eine Breite von 4 Bytes. Damit kann einem 4 Byte langen String genau eine 32-Bit-Zahl zugewiesen werden. Sobald Du ein Byte dazunimmst, muss es unweigerlich zu Kollisionen kommen (können).

Die Hashfunktion sollte natürlich so gewählt werden, dass die Wahrscheinlichkeit, dass im Fall von a.hashCode() == b.hashCode() die Gleichheit von a und b folgt, möglichst hoch ist (sprich: die Zahl der Kollisionen soll möglichst gering sein).
 

ocsme

Top Contributor
Also das bedeutet nun:
Java nimmt mir die Arbeit ab mir eine Hash Funktion einfallen zu lassen oder eine zu Implementieren die es so gibt.
Die Hash Funktion Prüft jedoch nur ob die Objekte ungleich sind.
Das bedeutet weiterhin ich benötige trotzdem eine equals Methode und sobald ich mehrere Objekte habe dann eben auch immer tiefere equals Methoden :(
das gefällt mir jetzt aber überhaupt nicht :(
Keine andere Alternative :D ???

Aber schon mal gut das hash nicht explizit gecodet werden muss denn daran wäre ich ja jetzt schon gescheitert da ich keine dieser Funktionen kenne und ich mich damit noch gar nicht auseinander gesetzt habe :D

Der "Vertrag" zwischen equals(Object) und hashcode() besagt, dass wenn 2 Objekte durch die equals(Object) Methode als gleich identifiziert werden, muss die hashcode() Methode den selben Integerwert zurückliefern.
Ja das habe ich auch vorhin gelesen :D
Gleichheit von Schlüsseln:

  • HashMap ruft auch die equals Methode auf um Gleichheit von Schlüsselobjekte festzustellen

  • Weiter verwenden viele Klassen des Collection-Frameworks die Methode hashCode

  • Dabei ist es unerlässlich das zwei Schlüsselobjekte den gleichen Hashcode liefern wenn sie laut equals gleich sind

  • equals und hashCode müssen also unbedingt im Einklang stehen

Wieso kann man in der Methode:
Java:
public static int hash(Object... values)
Ein Obejct varargs rein stecken?
 
Zuletzt bearbeitet:

Altairograph

Mitglied
Aus der Javadoc der Methode:

"
This method is useful for implementing Object.hashCode() on objects containing multiple fields. For example, if an object that has three fields, x, y, and z, one could write:

@Override public int hashCode() {
return Objects.hash(x, y, z);
}
..."

also wenn du ein Objekt hast dessen Felder wieder Objekte sind kannst du so leicht hashCode für dieses Objekt implementieren.

Ich mache gerade auf Udemy einen Spring-Kurs, und in dem kam vor dass wenn man mit Objekten arbeitet die zum Beispiel über Hibernate persistiert werden hashCode() sowas einfaches wie die generierte id zurückgeben kann. Also hashCode muss nichts kompliziertes sein solange der Code eben eindeutig ist (eindeutiges Mapping zwischen gehashtem Wert und resultierendem hash), IDEs haben (oder zumindest IntelliJ hat) zum Beispiel auch eine Funktionalität um die Implementierung von hashCode auf Basis von ausgewählten Feldern automatisch zu generieren.
 

mihe7

Top Contributor
Die Hash Funktion Prüft jedoch nur ob die Objekte ungleich sind.
Die Hashfunktion prüft gar nichts, sie bildet lediglich ein Objekt auf eine Zahl ab. Der Vertrag von Object verlangt dabei, dass für zwei Objekte, die gem. equals gleich sind, den gleichen Hashcode liefern müssen.

Daraus folgt, dass zwei Objekte, die unterschiedliche Hashcodes liefern, ungleich (gem. equals) sein müssen (denn wären sie gem. equals gleich, müssten sie ja den gleichen Hashcode liefern).

Das bedeutet weiterhin ich benötige trotzdem eine equals Methode und sobald ich mehrere Objekte habe dann eben auch immer tiefere equals Methoden :(
das gefällt mir jetzt aber überhaupt nicht
Ja, Du musst equals und hashCode praktisch immer gemeinsam überschreiben. Nur equals oder nur hashCode darf nicht sein, da sonst die von Object geforderten Eigenschaften nicht eingehalten werden.

Mal ein einfaches Beispiel:
Java:
public class Point {
    int x, y;
    public boolean equals(Object o) {
        if (o == null || o == this || !(o instanceof Point)) {
            return o == this;
        }
        Point p = (Point) o;
        return x == p.x && y == p.y;
    }

    public int hashCode() {
        return x;
    }
}
Das wäre eine gültige Implementierung, die allerdings sehr ungünstig ist, weil alle Punkte, die auf der gleichen x-Koordinate liegen, den gleichen Hashcode liefern. Umgekehrt ist klar: falls sich zwei Punkte in den x-Koordinaten unterscheiden, muss es sich um verschiedene Punkte handeln. D. h. liefert hashCode() unterschiedliche Werte, sind auch die Punkte unterschiedlich.

Man kann den Spaß verbessern:
Java:
    public int hashCode() { 
        return x + y;
    }
Jetzt liefern "nur" noch die Punkte, deren Summe aus x- und y-Koordinate gleich ist, den selben Hash-Code. Besser als nix.

Man kann z. B. mit der Cantorschen Paarungsfunktion für ein Zahlenpaar eine eindeutige Zahl (bijektiv) bestimmen. Das wäre in der Theorie das, was Du suchst:
Java:
    public int hashCode() {
        return (x+y)*(x+y+1)/2 + y;
    }
Allerdings macht Dir auch hier der Wertebereich von int einen Strich durch die Rechnung: die Berechnung wird relativ schnell zu einem Überlauf und damit auch zu Kollisionen führen.
 

ocsme

Top Contributor
Danke jetzt bin ich um einiges Schlauer :)
Das bedeutet nur immer wieder Arbeit vor allem mit dieser equals Methode.
Denn ich vermute mal wenn man einmal eine halbwegs "Ordentliche" Hashcode Funktion geschrieben hat ist der immer "save". Oder man nimmt eben die von Java :p
Mein größtes Problem besteht dann noch in der equals Methode :/

Danke nochmals :)

LG
 

ocsme

Top Contributor
o_O wie stellt diese Methode denn den Vergleich an ???
So jetzt bin ich wieder verwirrt :(

Die Arbeit mit dem paarweisen Vergleich bei Referenztypen besteht weiterhin nicht wahr?
_______________________

Und eine Frage hab ich von deinem Code von oben:
Java:
   if (o == null || o == this || !(o instanceof Point)) {

Wie ich mit null die Methode aufrufe weiß ich, wie ich die Methode mit einem anderen Objekt aufrufe ist auch Klar ABER wie kommt es den zum fall o == this?
equals(this)?

LG
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Der paarweise Vergleich bei Referenztypen nimmt mir aber die Methode: Objects.equals auch nicht ab! oder?
Du meinst alle Paare auf einmal? Nein, das nicht. Object.equals gibt für zwei angegebene Objekte o1 und o2 true zurück, gdw. eine der folgenden Bedingungen erfüllt ist:
1. o1 == null && o2 == null
2. o1 != null && o2 != null && o1.equals(o2)
Es ist also wesentlich schöner
Java:
if (Objects.equals(o1, o2)) {
schreiben zu können statt
Java:
if (o1 == null && o2 == null || o1 != null && o1.equals(o2)) {
...
 

ocsme

Top Contributor
Okay danke nochmals für das Feedback :)
Bin froh euch zu Haben :)

Jetzt ist erstmal alles gerade gerückt :D bis ich die nächsten Seiten meines Kapitels lese und wieder 1.000 Fragen im Kopf habe und nach erfolglosem google euch Frage :D

LG
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W Equals-Methode überschreiben bei composition Java Basics - Anfänger-Themen 20
C Long value an Stringbuilder übergeben, equals Methode funktioniert nicht Java Basics - Anfänger-Themen 2
J compareTo()- und equals-Methode Java Basics - Anfänger-Themen 3
NeoLexx equals()-Methode Verständnis Frage anhand Code Beispiel Java Basics - Anfänger-Themen 22
G Java equals() Methode Java Basics - Anfänger-Themen 9
H equals methode Java Basics - Anfänger-Themen 1
L Logistiksystem Methode equals und hashcode Java Basics - Anfänger-Themen 20
J Methoden Equals Methode für Integer und Objekte überschreiben? Java Basics - Anfänger-Themen 9
H equals Methode Java Basics - Anfänger-Themen 1
S equals Methode bei String Java Basics - Anfänger-Themen 5
K Vererbung equals-Methode bei Vererbung abstrakter Klassen Java Basics - Anfänger-Themen 8
SexyPenny90 Wieso ist diese eigene Equals-Methode schlecht? Java Basics - Anfänger-Themen 17
E Equals-Methode auf Class-Object Java Basics - Anfänger-Themen 17
J Methode equals() Java Basics - Anfänger-Themen 7
D Eigene equals methode schreiben Java Basics - Anfänger-Themen 4
A veränderbar kanonische Klassen: Methode equals, hashcode, serializable Java Basics - Anfänger-Themen 5
C 2 Objekte (mathematisch) vergleichen in der equals Methode Java Basics - Anfänger-Themen 10
C hilfe bei equals Methode - es geht ums Bestehen Java Basics - Anfänger-Themen 7
G equals-Methode Java Basics - Anfänger-Themen 4
Say Equals Java Basics - Anfänger-Themen 6
W LocalDate vergleichen mit Equals? Java Basics - Anfänger-Themen 7
W Wann und warum hashcode und equals? Java Basics - Anfänger-Themen 14
X Datentypen String.equals funktioniert nicht Java Basics - Anfänger-Themen 5
S 2 Strings mit Equals vergleichen Java Basics - Anfänger-Themen 11
lallmichnichtzu Methoden Überladen des .equals-Operators Java Basics - Anfänger-Themen 6
C Objekt1.equals(Objekt2) = immer false. Wieso? Java Basics - Anfänger-Themen 22
M Objekte mittels equals vergleichen Java Basics - Anfänger-Themen 14
S Interface Equals und hashCode Java Basics - Anfänger-Themen 16
J equals funktioniert nicht - Warum Java Basics - Anfänger-Themen 13
B Date - Vergleich (equals / after) ? Java Basics - Anfänger-Themen 3
G Ratlosigkeit zur Aufgabe im Anhang (boolean, equals.) Java Basics - Anfänger-Themen 20
D Unterschied == und equals in Arrays Java Basics - Anfänger-Themen 2
M Erste Schritte Mehrere eingaben in einer Line vergleichen (if equals...) Java Basics - Anfänger-Themen 6
I equals (Override) mit eigener Exception (keine Runtime-Exception) Java Basics - Anfänger-Themen 9
A OOP Richtige Verwendung von ArrayList und equals Java Basics - Anfänger-Themen 24
E equals Prüfung fehlgeschlagen Java Basics - Anfänger-Themen 3
C Objekt equals Java Basics - Anfänger-Themen 2
L String überprüfen mit .equals .contains oder .matches? Java Basics - Anfänger-Themen 1
F String equals NULL Problem Java Basics - Anfänger-Themen 4
D Auf equals von Vaterklasse zugreifen Java Basics - Anfänger-Themen 4
S Methoden equals(object o) / toString Java Basics - Anfänger-Themen 15
E Calender - Equals Problem Java Basics - Anfänger-Themen 14
T Datentypen compareTo() u. equals() bei Strings Java Basics - Anfänger-Themen 3
Psypsy hashCode, equals und toString Java Basics - Anfänger-Themen 3
K hashCode, compareTo vs. equals Java Basics - Anfänger-Themen 3
M Vergleich zweier Array Stellen mit equals/NullpointerException Java Basics - Anfänger-Themen 9
S Unterschiede zwischen equals und contains Java Basics - Anfänger-Themen 2
F Erste Schritte Hilfe bei Übung zu String equals() und Schleifen Java Basics - Anfänger-Themen 8
A Probleme mit equals und get.Text Java Basics - Anfänger-Themen 12
S compareTo() und equals() Java Basics - Anfänger-Themen 6
R illegal start of expression - 3 Strings vergleichen mit .equals () Java Basics - Anfänger-Themen 5
K Cast bei equals Java Basics - Anfänger-Themen 2
T SQL equals Java Basics - Anfänger-Themen 4
OnDemand Methoden Equals Methde Java Basics - Anfänger-Themen 3
D if block mit equals im rumpf Java Basics - Anfänger-Themen 11
K String - Equals Java Basics - Anfänger-Themen 2
J Klassen Warum ist (a.equals(b)) gleich (a==b)? Java Basics - Anfänger-Themen 13
B Warum gibst hier Equals false zurück ? Java Basics - Anfänger-Themen 23
S Verständnissfrage equals() Java Basics - Anfänger-Themen 2
R compareTo & equals Java Basics - Anfänger-Themen 10
M Verschiedene Möglichkeiten mit 'equals' abdecken? Java Basics - Anfänger-Themen 9
M Collections Problem bei Überschreibung von hashcode() und equals() bei Hashset-Implementierung Java Basics - Anfänger-Themen 5
W Stringvergleich mit equals Java Basics - Anfänger-Themen 13
C equals() Java Basics - Anfänger-Themen 4
D Problem mit string.equals bzw string.contains Java Basics - Anfänger-Themen 4
T Problem mit der while(!string.equals("x")) Java Basics - Anfänger-Themen 2
X problem mit equals.gelöst Java Basics - Anfänger-Themen 2
M Equals überschreiben Java Basics - Anfänger-Themen 3
K equals() und hashcode() überschreiben Java Basics - Anfänger-Themen 5
K equals in Hashmap() Java Basics - Anfänger-Themen 4
B if equals(irgendeine Zahl+Buchstabe) Java Basics - Anfänger-Themen 6
T equals() und hashCode() Java Basics - Anfänger-Themen 7
D probs mit clone und equals Java Basics - Anfänger-Themen 10
3 Collections containsKey() liefert false obwohl equals() true liefert Java Basics - Anfänger-Themen 6
N Vergleich per equals Java Basics - Anfänger-Themen 5
S comparable und equals Java Basics - Anfänger-Themen 7
M Frage zu Textvergleich (equals) Java Basics - Anfänger-Themen 8
G Strings vergleichen mit equals, geht das kürzer? Java Basics - Anfänger-Themen 4
B Frage zu Funktion mit equals Java Basics - Anfänger-Themen 17
J Gibt es eine möglichkeit ähnlich wie .equals(bedingung1 ||bedingung ..n) ? Java Basics - Anfänger-Themen 5
D "2010–03–12".equals( "2010-03-12" ) Java Basics - Anfänger-Themen 6
X Frage zur Implementierung von equals() Java Basics - Anfänger-Themen 2
T Problem mit equals Java Basics - Anfänger-Themen 5
K Equals,Instanceof und "==" Java Basics - Anfänger-Themen 7
C warum liefert equals kein TRUE Java Basics - Anfänger-Themen 12
E Java hashCode equals Problem Java Basics - Anfänger-Themen 2
S equals vergleich Java Basics - Anfänger-Themen 10
H Equals hascode Java Basics - Anfänger-Themen 5
S Equals Downcast? Java Basics - Anfänger-Themen 11
D equals Vergleiche Java Basics - Anfänger-Themen 7
L String mit equals vergleichen Java Basics - Anfänger-Themen 6
neurox Tutorial equals und hashCode überschreiben Java Basics - Anfänger-Themen 33
F String equals null wird nicht angenommen. Java Basics - Anfänger-Themen 24
A Reihenfolge bei equals() Java Basics - Anfänger-Themen 2
P Toleranz bei equals Java Basics - Anfänger-Themen 4
B Frage zu equals() und hashCode() Java Basics - Anfänger-Themen 28
D String#equals + String#charAt Java Basics - Anfänger-Themen 5
S equals() - hashCode() - Contract Java Basics - Anfänger-Themen 54
G mehrere Werte für .equals ? Java Basics - Anfänger-Themen 22
T [SOLVED] Java String equals funktioniert nicht Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben