Methoden hashCode() & equals()

friednoodles

Aktives Mitglied
Ich bin gerade dabei zu recherchieren wie sich hashCode() und equals() in z.B. einer HashMap verhalten.
Habe eine Sache bei der ich gerne wissen würde ob diese von mir richtig verstanden wurde.

-Die hashCode() Methode sollte nie einen fixen Wert zurück geben, da Objekte dann immer an der selben Stelle im Bucket gespeichert werden
und der Performance Vorteil für Zugriff, Suche und Einfügen verloren geht. Die O(1) Konstanten Zeiten werden damit zu O(n) linearen Zeiten. (O(n) bedeutet mit zunehmenden Objekten sinkt die Performance linear.

Das Überschreiben der equals() Methode bereitet mir ein wenig mehr Kopfschmerzen.

-Warum muss die equals() Methode aus der Object Klasse überschrieben werden?
-Was für einen Vorteil habe ich wenn meine Implementierung wie folgt aussieht?

Java:
public class User {

    private long id;
    private String name;
    private String email;

    //Kontruktoren, Getter, Setter

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null)
            return false;
        if (this.getClass() != o.getClass())
            return false;
        User user = (User) o;
        return id == user.id && (name.equals(user.name) && email.equals(user.email));
    }
}
 

mrBrown

Super-Moderator
Mitarbeiter
-Die hashCode() Methode sollte nie einen fixen Wert zurück geben, da Objekte dann immer an der selben Stelle im Bucket gespeichert werden
und der Performance Vorteil für Zugriff, Suche und Einfügen verloren geht. Die O(1) Konstanten Zeiten werden damit zu O(n) linearen Zeiten. (O(n) bedeutet mit zunehmenden Objekten sinkt die Performance linear.
In Bezug auf HashMap passt das.


-Warum muss die equals() Methode aus der Object Klasse überschrieben werden?
Weil diese Methode zum vergleichen von zwei Objekten benutzt wird.

-Was für einen Vorteil habe ich wenn meine Implementierung wie folgt aussieht?
Vorteil gegenüber was?

Vorteil gegenüber nicht überschriebener equals-Methode ist das Vorhandensein einer sinnvollen equals-Methode. Jetzt sind zwei User gleich, wenn ihre Attribute gleich sind, ohne wäre das nicht der Fall.
 
K

kneitzel

Gast
Mit equals erfolgt die Prüfung auf Gleichheit. Wenn Du diese nicht überschreibst, bleibt nur die Überprüfung, ob die Referenz gleich ist, aber das reicht nicht aus, sobald die Werte z.B. irgendwo gelesen werden. Und Du willst ja, dass zwei Instanzen mit den gleichen Werten, auch als gleich erkannt wird.

Die Implementation ist so ok. Generell muss man halt alle Fälle abdecken:
- null Wert übergeben
- Instanz einer anderen Klasse übergeben
- korrekte Instanz übergeben

Was mit aber bei Dir auffällt: Du rufst direkt auf name und email das equals auf. Wenn name oder email aber null ist, dann bekommst Du eine NPE.
Ich prüfe daher Strings generell mit Konstrukten wie:
(name != null ? name.equals(user.name) : user.name == null)
oder ich nutze eine Library, die mir z.B. eine statische Funktion equals(String, String) bietet (z.B. Apache commons StringUtils Klasse)
 

mihe7

Top Contributor
@friednoodles Und auch das hier
Java:
        if (this == o)
            return true;
        if (o == null)
            return false;
        if (this.getClass() != o.getClass())
            return false;
lässt sich schöner schreiben
Java:
        if (o == null || o == this || getClass() != o.getClass()) 
            return o == this;
 

mrBrown

Super-Moderator
Mitarbeiter
@friednoodles Und auch das hier
Java:
        if (this == o)
            return true;
        if (o == null)
            return false;
        if (this.getClass() != o.getClass())
            return false;
lässt sich schöner schreiben
Java:
        if (o == null || o == this || getClass() != o.getClass())
            return o == this;
Wobei Schönheit da im Auge des Betrachters liegt :p

Den Test auf this würd ich einzeln lassen, ist mMn einfacher lesbar und verständlicher.
 
K

kneitzel

Gast
Da würde mich einmal interessieren, in wie weit ihr denn sowas noch manuell schreibt oder ob ihr Lombok nutzt (oder etwas ähnliche, falls es da noch mehr Lösungen für gibt - ich kenne da erst einmal nur Lombok).

Java ist da halt sehr viel, was ich immer gerne als "EDV zu Fuss" bezeichne. Diese ganzen Getter und Setter zu schreiben ist halt einfach nur Tipparbeit. (Ich bin da von .Net mit den Properties dort halt anderes gewohnt. Und Kotlin, das ich einige Zeit genutzt habe, hat diesbezüglich auch keine "Probleme".)
 

mrBrown

Super-Moderator
Mitarbeiter
Da würde mich einmal interessieren, in wie weit ihr denn sowas noch manuell schreibt oder ob ihr Lombok nutzt (oder etwas ähnliche, falls es da noch mehr Lösungen für gibt - ich kenne da erst einmal nur Lombok).
Bisher meist alles händisch, sowohl equals (nach Bloch-Template) als auch Get/Setter - wobei händisch dabei IDE-generiert ist.

Ich bin allerdings sparsam mit Gettern und noch mehr mit Settern, und equals braucht meist auch nur die ID oder ein paar wenige Felder.
 

mihe7

Top Contributor

friednoodles

Aktives Mitglied
Danke für die bisherigen Antworten. Habe das alles soweit verstanden, aber würde gerne noch etwas Fragen bevor ich dafür extra einen neues Thema aufmache.

Kann man den Vorteil von Hashing gegenüber anderer Datenstrukturen in den konstant schnellen Operationen sehen?

Wie wird wenn ich die containsKey() Methode auf eine HashMap anwende der gesuchte key gefunden?
Ich habe in den vielen Tutorials bisher irgendwo einmal gelesen das der Hash vom ersten Entry generiert wird und von dort aus dann direkt ein Sprung zum gesuchten Element stattfindet. Stimmt das?
 

ARadauer

Top Contributor
Das Überschreiben der equals() Methode bereitet mir ein wenig mehr Kopfschmerzen.

-Warum muss die equals() Methode aus der Object Klasse überschrieben werden?
-Was für einen Vorteil habe ich wenn meine Implementierung wie folgt aussieht?
Wenn du equals nicht überschreibst wird geprüft ob sie die gleichen sind und nicht ob so gleich sind.
Unterschied klar?
Java:
public class User
{
    private long id;
    private String name;
    
    public User(long id, String name)
    {
        this.id = id;
        this.name = name;
    }

    public static void main(String[] args)
    {
        User u1 = new User(1, "Test");
        User u2 = new User(1, "Test");
        System.out.println(u1.equals(u2));
    }
}
false, das sind nicht die gleichen instanzen.
Was ist gleich? Das hängt im Grunde von der Fachlichkeit der Anwendung ab..

so sind sie gleich:
Java:
import java.util.Objects;

public class User
{
    private long id;
    private String name;

    public User(long id, String name)
    {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        User user = (User) o;
        return id == user.id &&
            Objects.equals(name, user.name);
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(id, name);
    }

    public static void main(String[] args)
    {
        User u1 = new User(1, "Test");
        User u2 = new User(1, "Test");
        System.out.println(u1.equals(u2));
    }
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I HashMap key wird nicht erkannt trotz überschriebener equals/hashCode Methode Allgemeine Java-Themen 6
fastjack jUnit und Test von equals, hashCode, toString Allgemeine Java-Themen 11
vogella Überschreiben von equals und hashcode für Collection Allgemeine Java-Themen 7
T HashCode korrekt Allgemeine Java-Themen 7
A JUnit/Hashcode Problem Allgemeine Java-Themen 5
pg1337 hashCode() verändert sich Allgemeine Java-Themen 15
A Input/Output Serialisierung und Object.hashCode() Allgemeine Java-Themen 3
M hashCode() Allgemeine Java-Themen 3
A HashCode von DatagrammPacket(content) erzeugen. Allgemeine Java-Themen 3
N hashCode() für zwei ints Allgemeine Java-Themen 5
C hashCode() Allgemeine Java-Themen 2
hdi Wahrscheinlichkeitsfrage bei hashCode() mit modulo Allgemeine Java-Themen 7
Guybrush Threepwood HashCode-Generierung Allgemeine Java-Themen 4
G hashCode() == Speicheradresse? => warum nur int? Allgemeine Java-Themen 28
X hashCode() Berechnung Allgemeine Java-Themen 5
M hashCode Allgemeine Java-Themen 9
T hashCode() erzeugen. Allgemeine Java-Themen 11
T eine Frage zu hashCode() Allgemeine Java-Themen 11
U Hashtables und hashCode() Allgemeine Java-Themen 6
mihe7 equals und instanceOf pattern matching Allgemeine Java-Themen 7
P Strings: equals vs == Allgemeine Java-Themen 47
J Equals Mock Objekte Allgemeine Java-Themen 5
J Mockito - Objekte miteinander vergleichen (equals) Allgemeine Java-Themen 6
J Probleme mit CodeCoverage und Lombok Equals Allgemeine Java-Themen 1
S equals-Methode bestimmer Klassen abfangen Allgemeine Java-Themen 2
T Zwei Wortendungen vergleichen ohne .equals Allgemeine Java-Themen 10
C Object.equals() liefert falschen Wert? Allgemeine Java-Themen 14
T Collections TreeSet.contains ruft nicht .equals? Allgemeine Java-Themen 4
H Problem mit der .equals()-Methode Allgemeine Java-Themen 2
T Compiler-Fehler not equals Allgemeine Java-Themen 22
V ArrayList vergleichen mit .equals? Allgemeine Java-Themen 13
A mit .equals Array befüllen schlägt teilweise fehl Allgemeine Java-Themen 3
G Probleme mit equals Allgemeine Java-Themen 3
R Merkwürdiges Verhalten der equals Method Allgemeine Java-Themen 4
tuttle64 equals() und == Allgemeine Java-Themen 4
B Probleme mit eigener equals Methode Allgemeine Java-Themen 18
H double dispatch und equals(Object) Allgemeine Java-Themen 6
S equals - Identität ändern bei Vererbung? Allgemeine Java-Themen 5
K Collection.contains()/retainAll() mit Referenzgleichheit statt equals()? Allgemeine Java-Themen 2
J Best Practice für implementierung von equals(...) Allgemeine Java-Themen 7
M equals & compareTo Allgemeine Java-Themen 15
M Warum Strings mit equals vergleichen... Allgemeine Java-Themen 6
T Wie intelligent ist dieses überschriebene .equals() ? Allgemeine Java-Themen 13
G Objektvergleich mit equals Allgemeine Java-Themen 5
M String#equals(), Probleme mit großen Strings? Allgemeine Java-Themen 4
André Uhres equals überschreiben Allgemeine Java-Themen 31
F Problem: mehrere Interfaces definieren equals() neu Allgemeine Java-Themen 24
A equals() macht nicht, was es soll Allgemeine Java-Themen 4
B Equals Methode überschreiben mit Array Allgemeine Java-Themen 2
M equals() != compareTo() ? Allgemeine Java-Themen 3
M String mit equals() vergleichen - Frage Allgemeine Java-Themen 3
S equals überladen Allgemeine Java-Themen 15
S Mal was allgemeines zu equals() Allgemeine Java-Themen 12
J Arrays vergleichen mit equals Allgemeine Java-Themen 8

Ähnliche Java Themen

Neue Themen


Oben